BZOJ2738:矩阵乘法——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2738
Description
给你一个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
整体二分二维版。
只需要把树状数组变成二维即可。
完后我们就对所有可行的取值二分然后就是整体二分的板子了。
(当然你也可以离散化)
#include<algorithm> #include<iostream> #include<cstring> #include<cctype> #include<cstdio> #include<vector> #include<cmath> using namespace std; const int N=510; const int Q=6e4+5; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct square{ int val,x,y; }v[N*N]; bool cmp(square a,square b){ return a.val<b.val; } struct question{ int lx,rx,ly,ry,k,id; }q[Q],tmp1[Q],tmp2[Q]; int ans[Q],tr[N][N]; int n,m,cnt; inline int lowbit(int t){return t&(-t);} inline void add(int x,int y,int z){ for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) tr[i][j]+=z; } inline int qry(int x,int y){ int res=0; for(int i=x;i;i-=lowbit(i)) for(int j=y;j;j-=lowbit(j)) res+=tr[i][j]; return res; } void solve(int L,int R,int l,int r){ if(L>R)return; if(l==r){ for(int i=L;i<=R;i++)ans[q[i].id]=v[l].val; return; } int idx1=0,idx2=0,mid=(l+r)>>1; for(int i=l;i<=mid;i++)add(v[i].x,v[i].y,1); for(int i=L;i<=R;i++){ int sum=qry(q[i].rx,q[i].ry)+ qry(q[i].lx-1,q[i].ly-1)- qry(q[i].rx,q[i].ly-1)- qry(q[i].lx-1,q[i].ry); if(sum>=q[i].k)tmp1[idx1++]=q[i]; else q[i].k-=sum,tmp2[idx2++]=q[i]; } for(int i=l;i<=mid;i++)add(v[i].x,v[i].y,-1); int MID=L+idx1; for(int i=L;i<MID;i++)q[i]=tmp1[i-L]; for(int i=MID;i<=R;i++)q[i]=tmp2[i-MID]; solve(L,MID-1,l,mid);solve(MID,R,mid+1,r); return; } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ v[++cnt].val=read(); v[cnt].x=i,v[cnt].y=j; } } sort(v+1,v+cnt+1,cmp); for(int i=1;i<=m;i++){ q[i].lx=read();q[i].ly=read(); q[i].rx=read();q[i].ry=read(); q[i].k=read();q[i].id=i; } solve(1,m,1,cnt); for(int i=1;i<=m;i++)printf("%d\n",ans[i]); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++