BZOJ2738: 矩陣乘法
阿新 • • 發佈:2018-08-12
ons block spa www. com pac discuss truct NPU
Submit: 1951 Solved: 855
[Submit][Status][Discuss]
接下來N行N列一共N*N個數,表示這個矩陣;
再接下來Q行每行5個數描述一個詢問:x1,y1,x2,y2,k表示找到以(x1,y1)為左上角、以(x2,y2)為右下角的子矩形中的第K小數。
對於每組詢問輸出第K小的數。
2 1
3 4
1 2 1 2 1
1 1 2 2 3
3
題解: 整體二分模板題 整體二分與CDQ的思想類似 我們考慮到二分答案 然後對於查詢的區間 我們考慮到當前的貢獻與期望貢獻的關系 然後分治查詢即可
#include <bits/stdc++.h> const int inf=1e9; using namespace std; typedef struct node{ int x,y,x1,y1,k;int ans,cnt; }node; node que[60005]; typedef struct Node{ int x,y,vul; friend bool operator<(Node aa,Node bb){return aa.vul<bb.vul;} }Node; Node a[300005]; int d[505][505],sz,n,m; int get_id(int x){return x&(-x);} void add(int x,int y,int vul){ for(int i=x;i<=n;i+=get_id(i)){ for(int j=y;j<=n;j+=get_id(j))d[i][j]+=vul; } } int Sum(int x,int y){ int sum1=0; for(int i=x;i>0;i-=get_id(i)){ for(int j=y;j>0;j-=get_id(j))sum1+=d[i][j]; } return sum1; } int querty(int pos){return Sum(que[pos].x1,que[pos].y1)+Sum(que[pos].x-1,que[pos].y-1)-Sum(que[pos].x-1,que[pos].y1)-Sum(que[pos].x1,que[pos].y-1);} int tot,id[60005],ed[60005],ip[60005]; void slove(int ql,int qr,int l,int r){ if(ql>qr||l==r)return ; int mid=(l+r)>>1; //cout<<l<<" "<<r<<endl; while(tot<sz&&a[tot+1].vul<=mid){ tot++; add(a[tot].x,a[tot].y,1); } while(tot&&a[tot].vul>mid){ add(a[tot].x,a[tot].y,-1); tot--; }int cnt=0,cnt1=0; //cout<<tot<<"===="<<mid<<" "<<ql<<" "<<qr<<" "<<que[id[1]].cnt<<endl; for(int i=ql;i<=qr;i++){ if(querty(id[i])>=que[id[i]].k)ed[++cnt]=id[i],que[id[i]].ans=mid; else ip[++cnt1]=id[i]; } for(int i=1;i<=cnt;i++)id[ql+i-1]=ed[i]; for(int i=1;i<=cnt1;i++)id[ql+cnt+i-1]=ip[i]; slove(ql,ql+cnt-1,l,mid); slove(ql+cnt,qr,mid+1,r); } int main(){ scanf("%d%d",&n,&m);sz=n*n; int vul;tot=0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&vul);a[(i-1)*n+j]=(Node){i,j,vul}; } } sort(a+1,a+sz+1); for(int i=1;i<=m;i++){ scanf("%d%d%d%d%d",&que[i].x,&que[i].y,&que[i].x1,&que[i].y1,&que[i].k); que[i].ans=que[i].cnt=0;id[i]=i; } slove(1,m,0,inf); for(int i=1;i<=m;i++)printf("%d\n",que[i].ans); return 0; }
2738: 矩陣乘法
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1951 Solved: 855
[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小數。
Output
Sample Input
2 22 1
3 4
1 2 1 2 1
1 1 2 2 3
Sample Output
13
HINT
矩陣中數字是109以內的非負整數;
20%的數據:N<=100,Q<=1000;
40%的數據:N<=300,Q<=10000;
60%的數據:N<=400,Q<=30000;
100%的數據:N<=500,Q<=60000。
BZOJ2738: 矩陣乘法