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
解题思路:
整体二分裸题,直接把区间第k大中的一维树状数组改成二维即可,也可以用扫描线,要快一点。
#include<bits/stdc++.h>
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=505,M=60005;
int n,m,cnt,bit[N][N],val[M],ans[M];
struct node{int x,y,val;}a[N*N];
inline bool cmp (const node &a,const node &b){return a.val<b.val;}
struct node1{int x1,y1,x2,y2,k,id;}q[M],t[M];
void insert(int x,int y,int v)
{
for(int i=x;i<=n;i+=i&(-i))
for(int j=y;j<=n;j+=j&(-j))
bit[i][j]+=v;
}
int query(int x,int y)
{
int res=0;
for(int i=x;i;i-=i&(-i))
for(int j=y;j;j-=j&(-j))
res+=bit[i][j];
return res;
}
void calc(int ql,int qr,int vl,int vr)
{
int l=1,r=cnt;
while(l<=r)
{
int mid=l+r>>1;
if(a[mid].val>=vl)r=mid-1;
else l=mid+1;
}
for(int i=ql;i<=qr;i++)val[i]=0;
if(l>cnt)return;
for(int i=l;a[i].val<=vr&&i<=cnt;i++)insert(a[i].x,a[i].y,1);
for(int i=ql;i<=qr;i++)
val[i]=query(q[i].x2,q[i].y2)+query(q[i].x1-1,q[i].y1-1)-query(q[i].x1-1,q[i].y2)-query(q[i].x2,q[i].y1-1);
for(int i=l;a[i].val<=vr&&i<=cnt;i++)insert(a[i].x,a[i].y,-1);
}
void solve(int ql,int qr,int vl,int vr)
{
if(ql>qr)return;
if(vl==vr)
{
for(int i=ql;i<=qr;i++)ans[q[i].id]=vl;
return;
}
int vmid=vl+vr>>1;
calc(ql,qr,vl,vmid);
int st=ql-1;
for(int i=ql;i<=qr;i++)
if(q[i].k<=val[i])t[++st]=q[i];
int qmid=st;
for(int i=ql;i<=qr;i++)
if(q[i].k>val[i])q[i].k-=val[i],t[++st]=q[i];
for(int i=ql;i<=qr;i++)q[i]=t[i];
solve(ql,qmid,vl,vmid),solve(qmid+1,qr,vmid+1,vr);
}
int main()
{
//freopen("lx.in","r",stdin);
//freopen("lx.out","w",stdout);
n=getint(),m=getint();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[++cnt]=(node){i,j,getint()};
sort(a+1,a+cnt+1,cmp);
for(int i=1;i<=m;i++)
{
q[i].x1=getint(),q[i].y1=getint();
q[i].x2=getint(),q[i].y2=getint();
q[i].k=getint(),q[i].id=i;
}
solve(1,m,0,1e9);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}