[BZOJ2738]矩阵乘法 整体二分+二维树状数组
Posted wls001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ2738]矩阵乘法 整体二分+二维树状数组相关的知识,希望对你有一定的参考价值。
2738: 矩阵乘法
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1643 Solved: 715
[Submit][Status][Discuss]
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。
先将矩阵中所有元素排序,然后对于所有询问一起二分
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 int n,q; 9 struct tmp { 10 int v,x,y; 11 bool operator <(const tmp &t)const { 12 return v<t.v; 13 } 14 }a[250005]; 15 int cnt=0; 16 struct data { 17 int x1,y1,x2,y2,k,id,ans; 18 }ask[60006],s[60005]; 19 int sum[505][505]; 20 int lowbit(int x){return x&(-x);} 21 void update(int x,int y,int add) { 22 for(int i=x;i<=n;i+=lowbit(i)) 23 for(int j=y;j<=n;j+=lowbit(j)) sum[i][j]+=add; 24 } 25 int query(int x,int y) { 26 int an=0; 27 for(int i=x;i>0;i-=lowbit(i)) 28 for(int j=y;j>0;j-=lowbit(j)) an+=sum[i][j]; 29 return an; 30 } 31 int get(int x1,int y1,int x2,int y2) { 32 return query(x2,y2)+query(x1-1,y1-1)-query(x1-1,y2)-query(x2,y1-1); 33 } 34 void solve(int l,int r,int ql,int qr) { 35 if(ql>qr) return; 36 if(l==r) { 37 for(int i=ql;i<=qr;i++) ask[i].ans=a[l].v; 38 return ; 39 } 40 int mid=(l+r)>>1; 41 for(int i=l;i<=mid;i++) update(a[i].x,a[i].y,1); 42 int head=ql-1,tail=0; 43 for(int i=ql;i<=qr;i++) { 44 int nowk=get(ask[i].x1,ask[i].y1,ask[i].x2,ask[i].y2); 45 if(nowk>=ask[i].k) ask[++head]=ask[i]; 46 else {s[++tail]=ask[i];s[tail].k-=nowk;} 47 } 48 for(int i=1;i<=tail;i++) ask[++head]=s[i]; 49 for(int i=l;i<=mid;i++) update(a[i].x,a[i].y,-1); 50 solve(l,mid,ql,qr-tail); 51 solve(mid+1,r,qr-tail+1,qr); 52 return ; 53 } 54 bool cmp(data t1,data t2) { 55 return t1.id<t2.id; 56 } 57 int main() { 58 scanf("%d%d",&n,&q); 59 for(int i=1;i<=n;i++) 60 for(int j=1;j<=n;j++){scanf("%d",&a[++cnt].v);a[cnt].x=i;a[cnt].y=j;} 61 sort(a+1,a+cnt+1); 62 for(int i=1;i<=q;i++) { 63 scanf("%d%d%d%d%d",&ask[i].x1,&ask[i].y1,&ask[i].x2,&ask[i].y2,&ask[i].k); 64 ask[i].id=i; 65 } 66 solve(1,cnt,1,q); 67 sort(ask+1,ask+1+q,cmp); 68 for(int i=1;i<=q;i++) printf("%d\n",ask[i].ans); 69 }
以上是关于[BZOJ2738]矩阵乘法 整体二分+二维树状数组的主要内容,如果未能解决你的问题,请参考以下文章