bzoj2738矩阵乘法

来源:互联网 发布:淘宝首页滚动图片尺寸 编辑:程序博客网 时间:2024/06/05 11:19

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

HINT

  矩阵中数字是109以内的非负整数;

  20%的数据:N<=100,Q<=1000;

  40%的数据:N<=300,Q<=10000;

  60%的数据:N<=400,Q<=30000;

  100%的数据:N<=500,Q<=60000。


据说正解是整体二分,然而看了半天并没有看懂,最后选择了分块
首先将矩阵里的数字排序,然后每次插size个,插入后暴力扫一遍询问,如果有询问的区间在本次操作中数字个数大于了k,就说明查询的k值在刚刚插入的
size个数中,此时再暴力倒序扫一遍刚刚的size个数字就好了,二位前缀和维护矩阵内数字的个数,链表维护询问即可
代码
#include <cstdio>#include <iostream>#include <algorithm>#include <cmath>#define maxn 505#define maxq 60005using namespace std;inline void read(int& x){char c=getchar();x=0;int y=1;while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();}while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();x*=y;}template<typename T>inline T m_min(T x,T y){return x<y?x:y;}int n,q,sum[maxn][maxn],sz,ans[maxq],done,cnt,pre[maxq],nex[maxq],A[maxn][maxn];struct query{int x1,x2,y1,y2,k;query(int a=0,int b=0,int c=0,int d=0,int e=0):x1(a),x2(b),y1(c),y2(d),k(e){}}Q[maxq];struct node{int x,y,v;node(int x=0,int y=0,int z=0):x(x),y(y),v(z){}friend bool operator<(const node& a,const node& b){return a.v<b.v;}}matrix[maxn*maxn];int main(){read(n);read(q);int x,y,a,b,c;for(int i=1;i<=n;++i)for(int j=1;j<=n;++j){read(x);matrix[++cnt]=node(i,j,x);}for(int i=1;i<=q;++i){read(x);read(y);read(a),read(b);read(c);Q[i]=query(x,a,y,b,c);pre[i]=i-1;nex[i]=i+1;}nex[0]=1;sort(matrix+1,matrix+cnt+1);register int i,j,k,lef,rig,_,__;int now;for(i=1;i<=n;++i){lef=(i-1)*n+1;rig=lef+n-1;for(j=lef;j<=rig;++j)A[matrix[j].x][matrix[j].y]=1;for(_=1;_<=n;++_)for(__=1;__<=n;++__)sum[_][__]=sum[_][__-1]+sum[_-1][__]-sum[_-1][__-1]+A[_][__];for(j=nex[0];j<=q;j=nex[j]){now=sum[Q[j].x2][Q[j].y2]-sum[Q[j].x2][Q[j].y1-1]-sum[Q[j].x1-1][Q[j].y2]+sum[Q[j].x1-1][Q[j].y1-1];if(now>=Q[j].k)for(int l=rig;l>=lef;--l)if(matrix[l].x>=Q[j].x1&&matrix[l].x<=Q[j].x2&&matrix[l].y>=Q[j].y1&&matrix[l].y<=Q[j].y2){   --now;if(now<Q[j].k){ans[j]=matrix[l].v;++done;nex[pre[j]]=nex[j];pre[nex[j]]=pre[j];break;}}}if(done==q) break;}for(int i=1;i<=q;++i) printf("%d\n",ans[i]);return 0;}


原创粉丝点击