洛谷P2468 SDOI 2010 粟粟的书架
题意:给你一个矩形书架,每个点是这本书的页数,每次询问(x1,y1)(x2,y2)这个小矩形里最少需要取几本书使得页数和等于Hi。
题解:小数据二位前缀和预处理+二分答案,大数据一行所以用主席树做,感觉数组开得玄学,洛谷上很好过,BZOJ经历了TLE->MLE->CE emmmmm,找不到CE在哪里。
#include<bits/stdc++.h> #define long long ll using namespace std; const int maxn=5e5+100; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,vv; int val[205][205][1005]; int sum[205][205][1005]; int cc[1005]; int page[205][205]; struct node { int l,r; int val,sum; }no[maxn*20]; inline int get_val(int x1,int y1,int x2,int y2,int k) { return val[x2][y2][k]-val[x1-1][y2][k]-val[x2][y1-1][k]+val[x1-1][y1-1][k]; } inline int get_sum(int x1,int y1,int x2,int y2,int k) { return sum[x2][y2][k]-sum[x1-1][y2][k]-sum[x2][y1-1][k]+sum[x1-1][y1-1][k]; } int rs,p,q,pp,qq; inline void work1() { int tmp=0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { page[i][j]=read(); cc[page[i][j]]++; if(page[i][j]>tmp)tmp=page[i][j]; } } for(int k=0;k<=tmp;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { val[i][j][k]=val[i-1][j][k]+val[i][j-1][k]-val[i-1][j-1][k]+(page[i][j]>=k?page[i][j]:0); sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k]+(page[i][j]>=k?1:0); } } } while(vv--) { p=read();q=read();pp=read();qq=read();rs=read(); if(get_val(p,q,pp,qq,0)<rs) { printf("Poor QLW\n"); continue; } int l=1,r=tmp,ans=-1; while(l<=r) { int mid=(l+r)>>1; if(get_val(p,q,pp,qq,mid)>=rs)l=mid+1,ans=mid; else r=mid-1; } if(ans==-1)printf("Poor QLW\n"); else{ int res=get_sum(p,q,pp,qq,ans)-(get_val(p,q,pp,qq,ans)-rs)/ans; printf("%d\n",res); } } } int cnt=0; int ssq[maxn]; int root[maxn]; void build(int &x,int l,int r) { x=++cnt; no[x].val=no[x].sum=0; if(l==r)return; int mid=(l+r)>>1; build(no[x].l,l,mid); build(no[x].r,mid+1,r); } void insertt(int&x,int pre,int l,int r,int pl) { x=++cnt; no[x]=no[pre]; no[x].sum++; no[x].val+=pl; if(l==r)return ; int mid=(l+r)>>1; if(pl<=mid)insertt(no[x].l,no[pre].l,l,mid,pl); else insertt(no[x].r,no[pre].r,mid+1,r,pl); } int query(int x,int pre,int l,int r,int rs) { if(l==r) { if(rs%l==0)return rs/l; return rs/l+1; } int mid=(l+r)>>1; int tmp=no[no[x].r].val-no[no[pre].r].val; int ans=0; if(tmp<rs) { rs-=tmp; ans+=no[no[x].r].sum-no[no[pre].r].sum; ans+=query(no[x].l,no[pre].l,l,mid,rs); } else{ ans+=query(no[x].r,no[pre].r,mid+1,r,rs); } return ans; } void work2() { int maxx=0; for(int i=1;i<=m;i++)ssq[i]=read(),maxx=max(ssq[i],maxx); build(root[0],1,maxx); for(int i=1;i<=m;i++)insertt(root[i],root[i-1],1,maxx,ssq[i]); while(vv--) { p=read();q=read();pp=read();qq=read();rs=read(); if(no[root[qq]].val-no[root[q-1]].val<rs) { printf("Poor QLW\n"); continue; } printf("%d\n",query(root[qq],root[q-1],1,maxx,rs)); } } int main() { n=read();m=read();vv=read(); if(n==1)work2(); else work1(); }