BZOJ 2738 矩阵乘法 (整体二分+二维树状数组)
题目大意:略
多次询问第k小,考虑整体二分
考虑二分答案,为了避免同一权值的数出现在不同位置的情况,用一个$vector$存储权值为i的点在那些位置。而权值可能会很大,我们将其离散。
每次选择一个答案$mid$,把矩阵中权值为$[l,mid]$的点加入到二维树状数组中,即可在$O(log^{2}n)$时间内,快速求出子矩阵内权值是$[l,mid]$的点的数量
如果这个数量小于某个询问的$k$,说明第$k$大的数一定大于$mid$,把它加入右区间递归
否则说明第$k$大的数小于等于$mid$,加入左区间递归
总时间$O((Q+n^{2})log^{3}n)$但树状数组常数小跑不满
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define N1 505 6 #define M1 60500 7 #define ll long long 8 #define dd double 9 #define inf 233333333 10 using namespace std; 11 12 int gint() 13 { 14 int ret=0,fh=1;char c=getchar(); 15 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 16 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 17 return ret*fh; 18 } 19 int n,m,nn,Q,K; 20 struct BIT{ 21 int sum[N1][N1]; 22 void update(int x,int y,int w) 23 { 24 for(int i=x;i<=n;i+=(i&(-i))) 25 for(int j=y;j<=n;j+=(j&(-j))) 26 sum[i][j]+=w; 27 } 28 int query(int x,int y) 29 { 30 int ans=0; 31 for(int i=x;i;i-=(i&(-i))) 32 for(int j=y;j;j-=(j&(-j))) 33 ans+=sum[i][j]; 34 return ans; 35 } 36 void clr(int x,int y) 37 { 38 for(int i=x;i<=n;i+=(i&(-i))) 39 for(int j=y;j<=n;j+=(j&(-j))) 40 sum[i][j]=0; 41 } 42 }s; 43 struct node{int x,y;}a[N1*N1]; 44 struct Query{int xa,ya,xb,yb,K,t;}q[M1],tmp[M1]; 45 int f[M1],mp[N1][N1],w[N1*N1],ma; 46 vector<node>pos[N1*N1]; 47 48 void alldic(int l,int r,int ql,int qr) 49 { 50 if(l>r||ql>qr) return; 51 int mid=(l+r)>>1,i,j,S=ql,E=qr,ans; 52 for(i=l;i<=mid;i++) for(j=0;j<pos[i].size();j++) 53 s.update(pos[i][j].x,pos[i][j].y,1); 54 for(i=ql;i<=qr;i++) 55 { 56 ans=s.query(q[i].xb,q[i].yb)+s.query(q[i].xa,q[i].ya)-s.query(q[i].xb,q[i].ya)-s.query(q[i].xa,q[i].yb); 57 if(ans<q[i].K){ q[i].K-=ans; tmp[E--]=q[i]; } 58 else{ tmp[S++]=q[i]; f[q[i].t]=w[mid]; } 59 } 60 for(i=ql;i<=qr;i++) q[i]=tmp[i]; 61 for(i=l;i<=mid;i++) for(j=0;j<pos[i].size();j++) 62 s.clr(pos[i][j].x,pos[i][j].y); 63 alldic(l,mid-1,ql,S-1); alldic(mid+1,r,E+1,qr); 64 } 65 66 67 int main() 68 { 69 scanf("%d%d",&n,&Q); 70 int i,j; nn=n*n; 71 for(i=1,nn=0;i<=n;i++) for(j=1;j<=n;j++) mp[i][j]=gint(),w[++nn]=mp[i][j]; 72 sort(w+1,w+nn+1); ma=unique(w+1,w+nn+1)-(w+1); 73 for(i=1;i<=n;i++) for(j=1;j<=n;j++) 74 { mp[i][j]=lower_bound(w+1,w+ma+1,mp[i][j])-w; pos[mp[i][j]].push_back((node){i,j}); } 75 for(i=1;i<=Q;i++) 76 { q[i].xa=gint()-1; q[i].ya=gint()-1; q[i].xb=gint(); q[i].yb=gint(); q[i].K=gint(); q[i].t=i; } 77 alldic(1,ma,1,Q); 78 for(i=1;i<=Q;i++) printf("%d\n",f[i]); 79 return 0; 80 }