Bzoj2738 矩阵乘法
Submit: 1471 Solved: 632
Description
给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。
Input
第一行两个数N,Q,表示矩阵大小和询问组数;
接下来N行N列一共N*N个数,表示这个矩阵;
再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。
接下来N行N列一共N*N个数,表示这个矩阵;
再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。
Output
对于每组询问输出第K小的数。
Sample Input
2 2
2 1
3 4
1 2 1 2 1
1 1 2 2 3
2 1
3 4
1 2 1 2 1
1 1 2 2 3
Sample Output
1
3
3
HINT
矩阵中数字是109以内的非负整数;
20%的数据:N<=100,Q<=1000;
40%的数据:N<=300,Q<=10000;
60%的数据:N<=400,Q<=30000;
100%的数据:N<=500,Q<=60000。
Source
分治 整体二分
二分一个答案,然后处理所有询问,把答案小于当前尝试值的和大于当前值的询问分别递归处理。
54行的保护机制似乎并没有什么用,一定要像74和76行那样加上if判断才能防止爆炸,迷。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=510; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct num{ 17 int x,y,w; 18 bool operator < (const num b)const{ 19 return w<b.w; 20 } 21 }a[mxn*mxn]; 22 int t[mxn][mxn]; 23 int n; 24 void add(int x,int y,int v){ 25 while(x<=n){ 26 int tmp=y; 27 while(tmp<=n){t[x][tmp]+=v; tmp+=tmp&-tmp;} 28 x+=x&-x; 29 } 30 return; 31 } 32 int smm(int x,int y){ 33 int res=0; 34 while(x){ 35 int tmp=y; 36 while(tmp){res+=t[x][tmp]; tmp-=tmp&-tmp;} 37 x-=x&-x; 38 } 39 return res; 40 } 41 inline int ask(int x1,int y1,int x2,int y2){ 42 return smm(x2,y2)-smm(x1-1,y2)-smm(x2,y1-1)+smm(x1-1,y1-1); 43 } 44 struct query{ 45 int x1,y1,x2,y2; 46 int k,id; 47 }q[mxn*120]; 48 int now[mxn*120],tmp[mxn*120]; 49 int ans[mxn*120]; 50 int Q,ed; 51 void solve(int l,int r,int L,int R){//答案区间,询问区间 52 // printf("l:%d r:%d L:%d R:%d\n",l,r,L,R); 53 if(l>r || L>R)return; 54 // if(l==r)return; 55 int mid=(a[l].w+a[r].w)>>1; 56 int i,j,cnt=0; 57 for(i=l;i<=r && a[i].w<=mid;i++){add(a[i].x,a[i].y,1);++cnt;} 58 int el=L-1,er=R+1,c; 59 for(i=L;i<=R;i++){ 60 c=now[i]; 61 int res=ask(q[c].x1,q[c].y1,q[c].x2,q[c].y2); 62 if(res>=q[c].k){ 63 ans[q[c].id]=mid; 64 tmp[++el]=c; 65 } 66 else{//res<q[c].k 67 tmp[--er]=c; 68 q[c].k-=res; 69 } 70 } 71 for(i=l;i<=r && a[i].w<=mid;i++){add(a[i].x,a[i].y,-1);} 72 for(i=L;i<=R;i++){now[i]=tmp[i];} 73 // if(l+cnt-1!=r || el!=R)solve(l,l+cnt-1,L,el); 74 if(l+cnt-1!=r || el!=R)solve(l,l+cnt-1,L,el); 75 // if(l+cnt!=l || er!=L) solve(l+cnt,r,er,R); 76 if(l+cnt!=l || er!=L) solve(l+cnt,r,er,R); 77 return; 78 } 79 int tct=0; 80 int main(){ 81 // freopen("in.txt","r",stdin); 82 int i,j,x; 83 n=read();Q=read(); 84 ed=n*n; 85 for(i=1;i<=n;i++) 86 for(j=1;j<=n;j++){ 87 a[++tct].x=i; a[tct].y=j; 88 a[tct].w=read(); 89 } 90 sort(a+1,a+ed+1); 91 for(i=1;i<=Q;i++){ 92 q[i].x1=read(); q[i].y1=read(); 93 q[i].x2=read(); q[i].y2=read(); 94 q[i].k=read(); q[i].id=i; 95 now[i]=i; 96 } 97 solve(1,ed,1,Q); 98 for(i=1;i<=Q;i++)printf("%d\n",ans[i]); 99 return 0; 100 }
本文为博主原创文章,转载请注明出处。