[BZOJ2738]矩阵乘法
生活随笔
收集整理的這篇文章主要介紹了
[BZOJ2738]矩阵乘法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[BZOJ2738]矩陣乘法
題面
給你一個N*N的矩陣,不用算矩陣乘法,但是每次詢問一個子矩形的第K小數。
Input
一行兩個數N,Q,表示矩陣大小和詢問組數;
接下來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 3Sample Output
1 3Hint
矩陣中數字是1e9以內的非負整數;
20%的數據:N<=100,Q<=1000;
40%的數據:N<=300,Q<=10000;
60%的數據:N<=400,Q<=30000;
100%的數據:N<=500,Q<=60000。
思路
整體二分。
對于每個查詢操作,我們只需要判斷整個矩陣內小于mid的元素個數然后即可分類遞歸。因為對于整體二分,所有的初始值都是以插入操作的形式完成的。所以我們用二維樹狀數組記錄所有權值小于\(mid\)的元素組成的矩陣(矩陣大小不變,大于\(mid\)的數用0代替)。這樣我們就可以使用二維樹狀數組來計算一個子矩陣的大小了。
代碼
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define maxn 550 #define inf (int)(1e9+1000) #define maxsize maxn*maxn+65000 int c[maxn][maxn]; struct gg{int ty,ux,uy,dx,dy,k,id; }q[maxsize],q1[maxsize],q2[maxsize]; int n,m,cnt,ans[maxsize]; inline int low(int x){return x&-x;} void add(int x,int y,int num){for(int i=x;i<=n;i+=low(i)){for(int j=y;j<=n;j+=low(j)){c[i][j]+=num;}} } int get(int x,int y){int sum=0;for(int i=x;i>=1;i-=low(i)){for(int j=y;j>=1;j-=low(j)){sum+=c[i][j];}}return sum; } int query(int ux,int uy,int dx,int dy){return get(dx,dy)-get(dx,uy-1)-get(ux-1,dy)+get(ux-1,uy-1); } void solve(int l,int r,int L,int R){if(l>r||L>R){return;}if(l==r){for(int i=L;i<=R;i++){if(q[i].ty==1){ans[q[i].id]=l;}}return;}int mid=(l+r)>>1;int cnt1=0,cnt2=0;for(int i=L;i<=R;i++){if(q[i].ty){int tmp=query(q[i].ux,q[i].uy,q[i].dx,q[i].dy);if(q[i].k<=tmp){q1[++cnt1]=q[i];}else{q[i].k-=tmp;q2[++cnt2]=q[i];}}else{if(q[i].k<=mid){add(q[i].ux,q[i].uy,1);q1[++cnt1]=q[i];}else{q2[++cnt2]=q[i];} }}for(int i=1;i<=cnt1;i++){if(!q1[i].ty)add(q1[i].ux,q1[i].uy,-1);}for(int i=1;i<=cnt1;i++){q[L+i-1]=q1[i];}for(int i=1;i<=cnt2;i++){q[L+i+cnt1-1]=q2[i];}solve(l,mid,L,L+cnt1-1);solve(mid+1,r,L+cnt1,R);return; } int main(){//freopen("in","r",stdin);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){q[++cnt]=(gg){0,i,j,i,j};scanf("%d",&q[cnt].k);}}for(int i=1;i<=m;i++){int a[10];scanf("%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5]);q[++cnt]=(gg){1,a[1],a[2],a[3],a[4],a[5],i};}solve(-inf,inf,1,cnt);for(int i=1;i<=m;i++){printf("%d\n",ans[i]);}return 0; }轉載于:https://www.cnblogs.com/GavinZheng/p/10910927.html
總結
以上是生活随笔為你收集整理的[BZOJ2738]矩阵乘法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 189-旋转数组
- 下一篇: 《机器学习实战》-线性回归