日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[BZOJ2738]矩阵乘法

發布時間:2024/1/17 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [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 3

Sample Output

1 3

Hint

  矩陣中數字是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]矩阵乘法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。