【BZOJ】1926: [Sdoi2010]粟粟的书架(暴力+主席树)
题目
传送门:QWQ
分析
两道题目
第一问暴力预处理
用$ a[i][j][k] $和$ s[i][j][k] $ 表示从$ (1,1) $ 到 $ (i,j) $ 这个矩形中比k大的数的个数和这些数的和。
对于询问我们二分k,得出答案(最后还要减掉一些值一样的东西 详见代码)
第二问主席树
r=1时只有一个数列,我们要求的是用多少数可以大于等于h
用主席树搞,询问时就像询问区间第k大时一样向左向右走,只不过要再套个二分。
代码
#include <bits/stdc++.h> using namespace std; const int maxn=501000; int s[205][205][1005],a[205][205][1005],p[205][205]; int rt[maxn], newp, ls[11000000], rs[11000000], sum[11000000], v[11000000]; //int rt[maxn], newp, ls[10000100], rs[10000100], sum[10000100], v[10000100]; int r,c,m; inline int in() { char c=getchar();int x=0; while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x; } void insert(int l,int r,int x,int &cur,int cur1){ cur=++newp; ls[cur]=ls[cur1]; rs[cur]=rs[cur1]; sum[cur]=sum[cur1]+x; v[cur]=v[cur1]+1; if(l==r) return; int mid=l+r>>1; if(x<=mid) /*ls[cur]=ls[cur1],*/insert(l,mid,x,ls[cur],ls[cur1]); else /*rs[cur]=rs[cur1],*/insert(mid+1,r,x,rs[cur],rs[cur1]); } int query(int x,int y,int h) { x=rt[x-1];y=rt[y]; if(sum[y]-sum[x]<h) return -1; int l=1,r=1000,ans=0; while(l<r){ int mid=(l+r)>>1; if(sum[rs[y]]-sum[rs[x]]<h){ ans+=v[rs[y]]-v[rs[x]]; h-=sum[rs[y]]-sum[rs[x]]; x=ls[x]; y=ls[y]; r=mid; // printf("----- %d\n",v[rs[y]]-v[rs[x]]); } else { l=mid+1; x=rs[x]; y=rs[y]; } } ans+=(h+l-1)/l; return ans; } int main() { r=in();c=in();m=in(); if(r!=1){ for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) p[i][j]=in(); for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) for(int k=1;k<=1000;k++) { a[i][j][k]=a[i-1][j][k]+a[i][j-1][k]-a[i-1][j-1][k]; s[i][j][k]=s[i-1][j][k]+s[i][j-1][k]-s[i-1][j-1][k]; if(p[i][j]>=k){ a[i][j][k]++; s[i][j][k]+=p[i][j]; } } while(m--){ int x1=in(),y1=in(),x2=in(),y2=in(),h=in(); int l=0,r=1001,ans; x1--;y1--; while(l+1<r){ int mid=(l+r)>>1;ans=s[x2][y2][mid]-s[x2][y1][mid]-s[x1][y2][mid]+s[x1][y1][mid]; if(ans>=h) l=mid; else r=mid; } int sum1=a[x2][y2][l]-a[x2][y1][l]-a[x1][y2][l]+a[x1][y1][l], sum2=s[x2][y2][l]-s[x2][y1][l]-s[x1][y2][l]+s[x1][y1][l]; if(l==0){puts("Poor QLW"); continue;} else printf("%d\n",sum1-(sum2-h)/l); } } else{ for(int i=1;i<=c;i++){ int t=in(); insert(1,1000,t,rt[i],rt[i-1]); } while(m--){ int x1=in(),y1=in(),x2=in(),y2=in(),h=in(); int ans=query(y1,y2,h); if(ans==-1) puts("Poor QLW"); else printf("%d\n",ans); } } return 0; }