zoukankan      html  css  js  c++  java
  • bzoj 1926: [Sdoi2010]粟粟的书架

    Description

    幸福幼儿园 B29 班的粟粟是一个聪明机灵、乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co
    rmen 的文章。粟粟家中有一个 R行C 列的巨型书架,书架的每一个位置都摆有一本书,上数第i 行、左数第j 列
    摆放的书有Pi,j页厚。粟粟每天除了读书之外,还有一件必不可少的工作就是摘苹果,她每天必须摘取一个指定的
    苹果。粟粟家果树上的苹果有的高、有的低,但无论如何凭粟粟自己的个头都难以摘到。不过她发现, 如果在脚
    下放上几本书,就可以够着苹果;她同时注意到,对于第 i 天指定的那个苹果,只要她脚下放置书的总页数之和
    不低于Hi,就一定能够摘到。由于书架内的书过多,父母担心粟粟一天内就把所有书看完而耽误了上幼儿园,于是
    每天只允许粟粟在一个特定区域内拿书。这个区域是一个矩形,第 i 天给定区域的左上角是上数第 x1i行的左数
    第 y1i本书,右下角是上数第 x2i行的左数第y2i本书。换句话说,粟粟在这一天,只能在这﹙x2i-x1i+1﹚×﹙
    y2i-y1i+1﹚本书中挑选若干本垫在脚下,摘取苹果。粟粟每次取书时都能及时放回原位,并且她的书架不会再
    撤下书目或换上新书,摘苹果的任务会一直持续 M天。给出每本书籍的页数和每天的区域限制及采摘要求,请你告
    诉粟粟,她每天至少拿取多少本书,就可以摘到当天指定的苹果。

    solution

    不知为何,全程没有注意到值域很小....这也是这题的关键
    对于前50分:
    (f[i][j][k]),表示前i行,前j列,大于等于k的数的和,(g[i][j][k]) 表示表示前i行,前j列,大于等于k的数的数量
    然后每一个询问二分最小的那本书的厚度就可以了
    对于后50分:
    前面的数组开不下了,但是只有一行,所以动态开点即可,做法和前面一样

    注意:对于多出来的部分要减去.

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    typedef long long ll;
    const int N=500005;
    int n,m,Q;
    namespace T2{
        int lim=0,a[205][205],f[205][205][1005];
        int g[205][205][1005],t[1005];
        inline int qsum(int xl,int yl,int xr,int yr,int k){
     return f[xr][yr][k]-f[xl-1][yr][k]-f[xr][yl-1][k]+f[xl-1][yl-1][k];
        }
        inline int qsize(int xl,int yl,int xr,int yr,int k){
     return g[xr][yr][k]-g[xl-1][yr][k]-g[xr][yl-1][k]+g[xl-1][yl-1][k];
        }
            
        void main(){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++){
                    scanf("%d",&a[i][j]);
                    f[i][j][a[i][j]]+=a[i][j];
                    g[i][j][a[i][j]]++;
                    if(a[i][j]>lim)lim=a[i][j];
                    t[a[i][j]]++;
                }
            for(int k=lim;k>=1;k--){
                if(t[k]){
                    for(int i=1;i<=n;i++){
                        for(int j=1;j<=m;j++)
                f[i][j][k]+=f[i][j-1][k]+f[i-1][j][k]-f[i-1][j-1][k],
                g[i][j][k]+=g[i][j-1][k]+g[i-1][j][k]-g[i-1][j-1][k];
                    }
                }
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=m;j++)
                 f[i][j][k]+=f[i][j][k+1],g[i][j][k]+=g[i][j][k+1];
            }
            int xl,yl,xr,yr,sum;
            while(Q--){
                scanf("%d%d%d%d%d",&xl,&yl,&xr,&yr,&sum);
                if(qsum(xl,yl,xr,yr,1)<sum){
                     puts("Poor QLW");continue;
                }
    
                int l=1,r=lim,mid,ret;
                while(l<=r){
                    mid=(l+r)>>1;
                    if(qsum(xl,yl,xr,yr,mid)>=sum)ret=mid,l=mid+1;
                    else r=mid-1;
                }
    
                int ans=qsize(xl,yl,xr,yr,ret);
                int res=qsum(xl,yl,xr,yr,ret)-sum;
                ans=ans-res/ret;
                printf("%d
    ",ans);
            }
        }
    }
    namespace T1{
        int a[N],totnode=0,root[N],rsum[N];
        struct node{
            int l,r,val,sz;
        }tr[N*20];
        inline void ins(int &x,int y,int l,int r,int sa){
            x=++totnode;tr[x]=tr[y];tr[x].sz++;
            if(l==r){tr[x].val+=l;return ;}
            int mid=(l+r)>>1;
            if(sa<=mid)ins(tr[x].l,tr[y].l,l,mid,sa);
            else ins(tr[x].r,tr[y].r,mid+1,r,sa);
            tr[x].val=tr[tr[x].l].val+tr[tr[x].r].val;
        }
        inline int qry(int x,int y,int l,int r,int sum){
            if(l==r){
                int res=tr[y].val-tr[x].val-sum;
                int ret=tr[y].sz-tr[x].sz;
                return ret-res/l;
            }
            int mid=(l+r)>>1,v=tr[tr[y].r].val-tr[tr[x].r].val;
            int size=tr[tr[y].r].sz-tr[tr[x].r].sz;
            if(sum<=v)return qry(tr[x].r,tr[y].r,mid+1,r,sum);
            return size+qry(tr[x].l,tr[y].l,l,mid,sum-v);
        }
        void main(){
            for(int i=1;i<=m;i++)
              scanf("%d",&a[i]),rsum[i]=rsum[i-1]+a[i];
            for(int i=1;i<=m;i++)ins(root[i],root[i-1],1,1000,a[i]);
            int x,y,z;
            while(Q--){
                scanf("%d%d%d%d%d",&x,&x,&y,&y,&z);
                if(rsum[y]-rsum[x-1]<z)puts("Poor QLW");
                else printf("%d
    ",qry(root[x-1],root[y],1,1000,z));
            }
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&Q);
        if(n==1)T1::main();
        else T2::main();
        return 0;
    }
    
    
  • 相关阅读:
    一、【注解】Spring注解@ComponentScan
    一致性Hash算法
    垃圾回收器搭配和调优
    JVM的逃逸分析
    简单理解垃圾回收
    类加载机制和双亲委派模型
    VMWare15下安装CentOS7
    HBase协处理器(1)
    依赖注入的三种方式
    Javascript-设计模式_装饰者模式
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8012060.html
Copyright © 2011-2022 走看看