栗栗的书架

xiaoxiao2021-02-28  17

本以为是线段树套主席书 不过看数据做题,大数据只有一条线。。 二分一个厚度直接大数据主席书 小数据暴力dp

// luogu-judger-enable-o2 // luogu-judger-enable-o2 // luogu-judger-enable-o2 #include<cstdio> #include<iostream> #define mid (l+r>>1) using namespace std; const int M=1000010; int n,m,root[M],tot=0,a[2][M],q,b[201][201],maxn,sum[201][201][1010],num[201][201][1001]; struct OL_SEG{ int l,r,num,sum;OL_SEG(){l=r=num=sum=0;} }T[M]; void update(int o){T[o].sum=T[T[o].l].sum+T[T[o].r].sum;} void modify(int &o,int pre,int l,int r,int ins){ o=++tot;T[o]=T[pre];T[o].num++; if(l==r) {T[o].sum=T[o].num*l;return ;} if(ins<=mid)modify(T[o].l,T[pre].l,l,mid,ins); else modify(T[o].r,T[pre].r,mid+1,r,ins); update(o); } int query(int pre,int now,int l,int r,int ql,int qr) { if(l>qr||r<ql) return 0; if(ql<=l&&r<=qr) return T[now].sum-T[pre].sum; return query(T[pre].l,T[now].l,l,mid,ql,qr)+query(T[pre].r,T[now].r,mid+1,r,ql,qr); } int query2(int pre,int now,int l,int r,int ql,int qr) { if(l>qr||r<ql) return 0; if(ql<=l&&r<=qr) return T[now].num-T[pre].num; return query2(T[pre].l,T[now].l,l,mid,ql,qr)+query2(T[pre].r,T[now].r,mid+1,r,ql,qr); } int ask(int x,int y,int xx,int yy,int w){return sum[xx][yy][w]-sum[x][yy][w]-sum[xx][y][w]+sum[x][y][w];} int ask2(int x,int y,int xx,int yy,int w){return num[xx][yy][w]-num[x][yy][w]-num[xx][y][w]+num[x][y][w];} int main(){ scanf("%d%d%d",&n,&m,&q); if(n==1){for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]),modify(root[j],root[j-1],0,1000,a[i][j]); while(q--){int x,y,xx,yy,h; scanf("%d%d%d%d%d",&x,&y,&xx,&yy,&h); int l=0,r=10000000; while(l<=r){ if(query(root[y-1],root[yy],0,1000,mid,1000)>=h) l=mid+1; else r=mid-1; } if(!l) {printf("Poor QLW\n");continue;} int w1=query(root[y-1],root[yy],0,1000,l-1,1000),w2=query2(root[y-1],root[yy],0,1000,l-1,1000); while(w1-l+1>=h)w1-=l-1,w2--; printf("%d\n",w2); } }else{ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&b[i][j]),maxn=max(maxn,b[i][j]); for(int i=0;i<=maxn;i++)for(int j=1;j<=n;j++)for(int k=1;k<=m;k++) sum[j][k][i]=sum[j][k-1][i]+sum[j-1][k][i]-sum[j-1][k-1][i]+((b[j][k]>=i)?b[j][k]:0), num[j][k][i]=num[j][k-1][i]+num[j-1][k][i]-num[j-1][k-1][i]+((b[j][k]>=i)?1:0); while(q--){int x,y,xx,yy,h; scanf("%d%d%d%d%d",&x,&y,&xx,&yy,&h); int l=0,r=maxn+1; while(l<=r){ if(ask(x-1,y-1,xx,yy,mid)>=h) l=mid+1; else r=mid-1; } if(!l) {printf("Poor QLW\n");continue;} int w1=ask(x-1,y-1,xx,yy,l-1),w2=ask2(x-1,y-1,xx,yy,l-1); while(w1-l+1>=h)w1-=l-1,w2--; printf("%d\n",w2); } } }
转载请注明原文地址: https://www.6miu.com/read-1999964.html

最新回复(0)