bzoj1926: [Sdoi2010]粟粟的书架

题目链接

传送门

题解

大佬好强

看了看数据范围,不是很明白为什么明明两道题却硬要挤在一道题里

0.5倍经验orz……

前一半的数据$R,C<=200$

前缀和+二分

$num[i][j][k]表示(1,1)到(i,j)中比大于等于k的数有几个$
$sum[i][j][k]表示(1,1)到(i,j)中比大于等于k的数的总和$

二分找k+1,对k直接暴力填

后一半的数据就是个序列

直接开个主席树

二分一下取多少本书

然后直接树上跑一跑就行

ps:主席树查询时应优先挑选高度更高的书,原因应该不用解释

  1 // luogu-judger-enable-o2
  2 //minamoto
  3 #include<bits/stdc++.h>
  4 using namespace std;
  5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  6 char buf[1<<21],*p1=buf,*p2=buf;
  7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
  8 inline int read(){
  9     #define num ch-'0'
 10     char ch;bool flag=0;int res;
 11     while(!isdigit(ch=getc()))
 12     (ch=='-')&&(flag=true);
 13     for(res=num;isdigit(ch=getc());res=res*10+num);
 14     (flag)&&(res=-res);
 15     #undef num
 16     return res;
 17 }
 18 int n,m,q;
 19 namespace solve1{
 20     #define N 205
 21     int a[N][N],num[N][N][1005],sum[N][N][1005];
 22     int mx=0;
 23     int getsum(int a,int b,int c,int d,int h){
 24         return sum[c][d][h]-sum[c][b][h]-sum[a][d][h]+sum[a][b][h];
 25     }
 26     int getnum(int a,int b,int c,int d,int h){
 27         return num[c][d][h]-num[c][b][h]-num[a][d][h]+num[a][b][h];
 28     }
 29     int getans(int a,int b,int c,int d,int k,int need){
 30         int res=getnum(a,b,c,d,k+1);
 31         need-=getsum(a,b,c,d,k+1);
 32         if(need>=0){
 33             int num=need/k;
 34             res+=num;
 35             need-=num*k;
 36             if(need>0) ++res,need-=k;
 37         }
 38         return res;
 39     }
 40     bool check(int a,int b,int c,int d,int mid,int h){
 41         return getsum(a,b,c,d,mid)>h?1:0;
 42     }
 43     void main(){
 44         for(int i=1;i<=n;++i)
 45         for(int j=1;j<=m;++j)
 46         cmax(mx,a[i][j]=read());
 47         for(int k=0;k<=mx;++k)
 48         for(int i=1;i<=n;++i)
 49         for(int j=1;j<=m;++j){
 50             num[i][j][k]=num[i-1][j][k]+num[i][j-1][k]-num[i-1][j-1][k]+(a[i][j]>=k?1:0);
 51             sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k]+(a[i][j]>=k?a[i][j]:0);
 52         }
 53         while(q--){
 54             int a,b,c,d,h;
 55             a=read(),b=read(),c=read(),d=read(),h=read();
 56             --a,--b;
 57             if(getsum(a,b,c,d,0)<h){
 58                 puts("Poor QLW");continue;
 59             }
 60             int l=1,r=mx,ans=0;
 61             while(l<=r){
 62                 int mid=(l+r)>>1;
 63                 if(check(a,b,c,d,mid,h)) ans=mid,l=mid+1;
 64                 else r=mid-1;
 65             }
 66             if(!ans) ans=1;
 67             printf("%d\n",getans(a,b,c,d,ans,h));
 68         }
 69     }
 70     #undef N
 71 }
 72 namespace solve2{
 73     #define N 500005
 74     int sum[N<<4],L[N<<4],R[N<<4],sz[N<<4];
 75     int rt[N];
 76     int mx=0,cnt=0;
 77     void update(int last,int &now,int l,int r,int x){
 78         sz[now=++cnt]=sz[last]+1,sum[now]=sum[last];
 79         if(l==r){sum[now]+=x;return;}
 80         int mid=(l+r)>>1;
 81         if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
 82         else L[now]=L[last],update(R[last],R[now],mid+1,r,x);
 83         sum[now]=sum[L[now]]+sum[R[now]];
 84     }
 85     int query(int u,int v,int l,int r,int k){
 86         if(sz[v]-sz[u]<=k) return sum[v]-sum[u];
 87         if(l==r) return (sum[v]-sum[u])/(sz[v]-sz[u])*k;
 88         int mid=(l+r)>>1;
 89         if(sz[R[v]]-sz[R[u]]>=k) return query(R[u],R[v],mid+1,r,k);
 90         else return query(L[u],L[v],l,mid,k-(sz[R[v]]-sz[R[u]]))+sum[R[v]]-sum[R[u]];
 91     }
 92     void main(){
 93         mx=1000;
 94         for(int i=1;i<=m;++i){
 95             int x=read();
 96             update(rt[i-1],rt[i],1,mx,x);
 97         }
 98         while(q--){
 99             int a=read(),b=read(),c=read(),d=read(),h=read();
100             --b;
101             int l=1,r=d-b+1;
102             while(l<r){
103                 int mid=(l+r)>>1;
104                 if(query(rt[b],rt[d],1,mx,mid)>=h) r=mid;
105                 else l=mid+1;
106             }
107             if(r==d-b+1) puts("Poor QLW");
108             else printf("%d\n",l);
109         }
110     }
111 }
112 int main(){
113     //freopen("testdata.in","r",stdin);
114     n=read(),m=read(),q=read();
115     if(n!=1) solve1::main();
116     else solve2::main();
117     return 0;
118 }

 

posted @ 2018-07-29 21:57  bztMinamoto  阅读(231)  评论(0编辑  收藏  举报
Live2D