与静态kth的做法可以说是一模一样,计数改为用二维树状数组即可。
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
using namespace std;
int n,m,x,a,b,c,d,k,minn,maxn,cnt;
int sum[505][505],ans[60005];
struct node{int id1,id2,id3,id4,id,k,opt;}q[310005],q1[310005],q2[310005];
inline void change(int x,int y,int v)
{
int yy=y;
while (x<=n)
{
y=yy;
while (y<=n)
{
sum[x][y]+=v;
y+=lowbit(y);
}
x+=lowbit(x);
}
}
inline int query(int x,int y)
{
int res=0;
int yy=y;
while (x)
{
y=yy;
while (y)
{
res+=sum[x][y];
y-=lowbit(y);
}
x-=lowbit(x);
}
return res;
}
inline int querysum(int a,int b,int c,int d)
{
return query(c,d)-query(c,b-1)-query(a-1,d)+query(a-1,b-1);
}
void solve(int ql,int qr,int l,int r)
{
if (ql>qr) return;
if (l==r)
{
for (register int i=ql; i<=qr; ++i) if (q[i].opt==2) ans[q[i].id]=l;
return;
}
int mid=l+r>>1;
int p1=0,p2=0;
for (register int i=ql; i<=qr; ++i)
if (q[i].opt==1)
{
if (q[i].id1<=mid)
{
change(q[i].id3,q[i].id4,1);
q1[++p1]=q[i];
}
else q2[++p2]=q[i];
}
else
{
int res=querysum(q[i].id1,q[i].id2,q[i].id3,q[i].id4);
if (q[i].k<=res) q1[++p1]=q[i];
else
{
q[i].k-=res;
q2[++p2]=q[i];
}
}
for (register int i=1; i<=p1; ++i) if (q1[i].opt==1) change(q1[i].id3,q1[i].id4,-1);
for (register int i=1; i<=p1; ++i) q[ql+i-1]=q1[i];
for (register int i=1; i<=p2; ++i) q[ql+p1-1+i]=q2[i];
solve(ql,ql+p1-1,l,mid);
solve(ql+p1,qr,mid+1,r);
}
int main(){
scanf("%d%d",&n,&m);
minn=1e9; maxn=0;
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=n; ++j)
{
scanf("%d",&x);
minn=min(minn,x);
maxn=max(maxn,x);
q[++cnt]=(node){x,0,i,j,0,0,1};
}
for (register int i=1; i<=m; ++i)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
q[++cnt]=(node){a,b,c,d,i,k,2};
}
solve(1,cnt,minn,maxn);
for (register int i=1; i<=m; ++i) printf("%d\n",ans[i]);
return 0;
}