bzoj2738: 矩阵乘法(整体二分)
http://www.lydsy.com/JudgeOnline/problem.php?id=2738
整体二分
二维树状数组累积
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 501 #define M 60001 #define lowbit(x) x&-x struct Number { int x,y,num; }e[N*N]; struct Query { int X1,Y1,X2,Y2; int k,cur; int id; }f[M],tmp1[M],tmp2[M]; int n; int c[N][N]; int ans[M],have[M]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } bool cmp(Number p,Number q) { return p.num<q.num; } void change(int x,int y,int w) { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) c[i][j]+=w; } int query(int x,int y) { int sum=0; for(int i=x;i;i-=lowbit(i)) for(int j=y;j;j-=lowbit(j)) sum+=c[i][j]; return sum; } void solve(int head,int tail,int l,int r) { if(head>tail) return; if(l==r) { for(int i=head;i<=tail;++i) ans[f[i].id]=e[l].num; return; } int mid=l+r>>1; for(int i=l;i<=mid;++i) change(e[i].x,e[i].y,1); for(int i=head;i<=tail;++i) have[f[i].id]=query(f[i].X2,f[i].Y2)-query(f[i].X1-1,f[i].Y2)-query(f[i].X2,f[i].Y1-1)+query(f[i].X1-1,f[i].Y1-1); for(int i=l;i<=mid;++i) change(e[i].x,e[i].y,-1); int ll=0,rr=0; for(int i=head;i<=tail;++i) { if(have[f[i].id]+f[i].cur>=f[i].k) tmp1[++ll]=f[i]; else { f[i].cur+=have[f[i].id]; tmp2[++rr]=f[i]; } } for(int i=1;i<=ll;++i) f[head+i-1]=tmp1[i]; for(int i=1;i<=rr;++i) f[head+ll+i-1]=tmp2[i]; solve(head,head+ll-1,l,mid); solve(head+ll,tail,mid+1,r); } int main() { int q; read(n); read(q); int tot=0; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { e[++tot].x=i; e[tot].y=j; read(e[tot].num); } sort(e+1,e+tot+1,cmp); for(int i=1;i<=q;++i) { read(f[i].X1); read(f[i].Y1); read(f[i].X2); read(f[i].Y2); read(f[i].k); f[i].id=i; } solve(1,q,1,tot); for(int i=1;i<=q;++i) cout<<ans[i]<<'\n'; }