BZOJ 2738: 矩阵乘法 [整体二分]
给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。
愚蠢的名字......
整体二分,影响因子就是矩阵里的数
把$\le mid$的矩阵元素加到二维树状数组里然后询问分成两组就行了
可以把矩阵元素权值排序后直接二分矩阵元素而不是值
复杂度$O(nlog^3n)$
用排序代替一维树状数组理论上更快,但需要把矩阵里的元素和查询放到一个数组里再排序貌似常数太大
然后发现黄学长的做法是错误的复杂度不对....但竟然比我快....
二维树状数组一定不要写错!!!
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=505,M=6e4+5,INF=1e9; typedef long long ll; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,Q; struct Factor{ int x,y,v; Factor(){} Factor(int a,int b,int c):x(a),y(b),v(c){} bool operator <(const Factor &r)const{return v<r.v;} }a[N*N]; int m,now=0; struct Query{ int x1,y1,x2,y2,k; }q[M]; int id[M],t1[M],t2[M],cur[M]; int c[N][N]; inline int lowbit(int x){return x&-x;} inline void add(int x,int y,int v){ for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) c[i][j]+=v; } inline int sum(int x,int y){ int re=0; for(int i=x;i;i-=lowbit(i)) for(int j=y;j;j-=lowbit(j)) re+=c[i][j]; return re; } inline int que(int i){ int x1=q[i].x1-1,y1=q[i].y1-1,x2=q[i].x2,y2=q[i].y2; return sum(x2,y2)-sum(x1,y2)-sum(x2,y1)+sum(x1,y1); } int ans[M]; void Sol(int l,int r,int ql,int qr){ if(ql>qr) return; if(l==r){ for(int i=ql;i<=qr;i++) ans[id[i]]=a[l].v; return; } int mid=(l+r)>>1; for(int i=l;i<=mid;i++) add(a[i].x,a[i].y,1); int p1=0,p2=0; for(int i=ql;i<=qr;i++){ int u=id[i],s=cur[u]+que(u); if(s>=q[u].k) t1[++p1]=u; else t2[++p2]=u,cur[u]=s; } for(int i=l;i<=mid;i++) add(a[i].x,a[i].y,-1); for(int i=1;i<=p1;i++) id[ql+i-1]=t1[i]; for(int i=1;i<=p2;i++) id[ql+p1+i-1]=t2[i]; Sol(l,mid,ql,ql+p1-1); Sol(mid+1,r,ql+p1,qr); } int main(){ freopen("in","r",stdin); n=read();Q=read(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[++m]=Factor(i,j,read()); for(int i=1;i<=Q;i++) q[i].x1=read(),q[i].y1=read(),q[i].x2=read(),q[i].y2=read(),q[i].k=read(); sort(a+1,a+1+m); for(int i=1;i<=Q;i++) id[i]=i; Sol(1,m,1,Q); for(int i=1;i<=Q;i++) printf("%d\n",ans[i]); }
Copyright:http://www.cnblogs.com/candy99/