题链:https://www.luogu.org/problemnew/show/P1527
感觉树套树可以,但是空间不够
没有修改,询问的类型相同,又可以离线,推测整体二分
试试看,发现是个二维整体二分
时间复杂度
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int read()
{
int ret=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9')
{
ret=(ret<<1)+(ret<<3)+ch-'0';
ch=getchar();
}
return ret;
}
void write(int x)
{
if((x/10)!=0) write(x/10);
putchar(x%10+48);
}
const int N=505,M=300005;
int n,m,ans[M],c[N][N],bb[M];
struct A{int x1,y1,x2,y2,k,id; }q[M],q1[M],q2[M];
struct B{int v,x,y; }b[M];
inline void add(int x,int y,int k)
{
for(int i=x;i<=n;i+=i&-i)
for(int j=y;j<=n;j+=j&-j)
c[i][j]+=k;
}
inline int sum(int x,int y)
{
int ret=0;
for(int i=x;i;i-=i&-i)
for(int j=y;j;j-=j&-j)
ret+=c[i][j];
return ret;
}
int find1(int x)
{
int l=1,r=n*n,ans=0;
while(l<=r)
{
int mid=l+r>>1;
if(b[mid].v>=x)
{
ans=mid; r=mid-1;
}
else l=mid+1;
}
return ans;
}
int find2(int x)
{
int l=1,r=n*n,ans=1;
while(l<=r)
{
int mid=l+r>>1;
if(b[mid].v<=x)
{
ans=mid; l=mid+1;
}
else r=mid-1;
}
return ans;
}
void solve(int l,int r,int L,int R,int loc)
{
if(L>R) return;
if(l==r)
{
for(int i=L;i<=R;i++)
ans[q[i].id]=l;
return;
}
int mid=l+r>>1;
if(loc!=0)
{
if(loc>mid)
{
int t1=find1(mid+1),t2=find2(loc);
for(int i=t1;i<=t2;i++)
add(b[i].x,b[i].y,-1);
}else
if(loc<mid)
{
int t1=find1(loc+1),t2=find2(mid);
for(int i=t1;i<=t2;i++)
add(b[i].x,b[i].y,1);
}
}else
{
int t1=find2(mid);
for(int i=1;i<=t1;i++)
add(b[i].x,b[i].y,1);
}
int j=0,k=0;
for(int i=L;i<=R;i++)
{
if(sum(q[i].x2,q[i].y2)-sum(q[i].x1-1,q[i].y2)-sum(q[i].x2,q[i].y1-1)+sum(q[i].x1-1,q[i].y1-1)>=q[i].k)
q1[++j]=q[i];
else
q2[++k]=q[i];
}for(int i=L;i<=L+j-1;i++)
q[i]=q1[i-L+1];
for(int i=L+j;i<=R;i++)
q[i]=q2[i-L-j+1];
solve(l,mid,L,L+j-1,mid);
solve(mid+1,r,L+j,R,mid);
if(loc!=0)
{
if(loc>mid)
{
int t1=find1(mid+1),t2=find2(loc);
for(int i=t1;i<=t2;i++)
add(b[i].x,b[i].y,1);
}else
if(loc<mid)
{
int t1=find1(loc+1),t2=find2(mid);
for(int i=t1;i<=t2;i++)
add(b[i].x,b[i].y,-1);
}
}else
{
int t1=find2(mid);
for(int i=1;i<=t1;i++)
add(b[i].x,b[i].y,-1);
}
}
bool cmp(B i,B j) { return i.v<j.v; }
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int t=read();
b[(i-1)*n+j]=(B){t,i,j};
}
sort(b+1,b+n*n+1,cmp);
int c=1;
for(int i=1;i<=n*n;i++)
{
bb[c]=b[i].v;
b[i].v=c;
if(i!=n*n&&b[i].v!=b[i+1].v)
c++;
}
for(int i=1;i<=m;i++)
{
q[i].x1=read(),q[i].y1=read();
q[i].x2=read(),q[i].y2=read();
q[i].k=read(),q[i].id=i;
}
solve(1,c,1,m,0);
for(int i=1;i<=m;i++)
write(bb[ans[i]]),puts("");
return 0;
}