整体二分
先把矩阵所有元素从小到大排序,然后对于每个矩形二分一个k,用二维树状数组check(即比他小的在那个矩形内的有多少个)。
复杂度好像是 O(n∗(logn)4)
//QWsin
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500+10;
const int maxn2=250000+10;
const int maxq=60000+10;
inline int read()
{
int ret=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
return ret;
}
int n,q,t[maxn2];
int C[maxn][maxn];
#define lowbit(i) ((i)&-(i))
inline void updata(int x,int y,int val){
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
C[i][j]+=val;
}
inline int query(int x,int y){
int ret=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j))
ret+=C[i][j];
return ret;
}
inline int query(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);
}
struct Node{
int x,y,num;
inline bool operator < (const Node &rhs)const{
return num<rhs.num;
}
inline void input(int i,int j){
x=i;y=j;num=read();
t[(i-1)*n+j]=num;
}
}a[maxn2];
struct ASK{
int a,b,c,d,k,t,id;
ASK(int a=0,int b=0,int c=0,int d=0,int k=0,int id=0):
a(a),b(b),c(c),d(d),k(k),id(id){}
};
int top=0,ans[maxq];
void solve(vector<ASK>ask,int l,int r)
{
if(l==r){
for(int i=0,sz=ask.size();i<sz;++i)
ans[ask[i].id]=l;
return ;
}
int mid=(l+r)>>1;
while(top<mid){
++top;updata(a[top].x,a[top].y,1);
}
while(top>mid){
updata(a[top].x,a[top].y,-1);--top;
}
vector<ASK>L,R;
for(int i=0,sz=ask.size();i<sz;++i){
ASK p=ask[i];
int t=query(p.a , p.b , p.c , p.d);
if(t>=p.k) L.push_back(ask[i]);
else R.push_back(ask[i]);
}
solve(L,l,mid);solve(R,mid+1,r);
}
int main()
{
freopen("std.in","r",stdin);
cin>>n>>q;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
a[(i-1)*n+j].input(i,j);
sort(a+1,a+n*n+1);
sort(t+1,t+n*n+1);
vector<ASK>ask;
for(int i=1,a,b,c,d,k;i<=q;++i){
a=read();b=read();c=read();d=read();k=read();
ask.push_back(ASK(a,b,c,d,k,i));
}
// for(int i=1;i<=n;++i) 卧槽啊你手残到这种地步,莫名其妙多出来一个for,T上天,而且把cdq注释了还是T上天。(手动再见)
solve(ask,1,n*n);//[l,r]是排序后的数组里的值
for(int i=1;i<=q;++i) printf("%d\n",t[ans[i]]);
return 0;
}