首先我们发现它是一个三维的问题而且还强制在线 囧
我们可以考虑在外面来一个权值线段树,然后每次查询时在线段树二分即可,这样我们每个节点再套一棵K-D tree,用来查询有多少个点被框住了,然后因为是不断往里插点,所以还要替罪羊式重构维护一下K-D tree。
最后复杂度就是
O(qlogwn−−√)
O
(
q
l
o
g
w
n
)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 500010
#define alpha 0.77
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,rt[N*6],D,Rt=0,owo=0,lc[N*6],rc[N*6],ofo=0,tot,lastans=0;
int *pp,ppop;
struct point{
int d[2],id;
int& operator[](int x){return d[x];}
friend bool operator<(point a,point b){return a[D]<b[D];}
}t1,t2,a[N];
struct node{
point x;int lc,rc,mx[2],mn[2],sz;
}tr[N*6];
inline void update(int p){
int l=tr[p].lc,r=tr[p].rc;
for(int i=0;i<2;++i){
tr[p].mx[i]=max(tr[p].x[i],max(tr[l].mx[i],tr[r].mx[i]));
tr[p].mn[i]=min(tr[p].x[i],min(tr[l].mn[i],tr[r].mn[i]));
}tr[p].sz=tr[l].sz+tr[r].sz+1;
}
inline void ins(int &p,int op){
if(!p){p=++ofo;tr[p].x=t1;update(p);return;}D=op;
if(t1<tr[p].x) ins(tr[p].lc,op^1);
else ins(tr[p].rc,op^1);update(p);
if(max(tr[tr[p].lc].sz,tr[tr[p].rc].sz)>tr[p].sz*alpha) pp=&p,ppop=op;
}
void dfs(int p){
a[++tot]=tr[p].x;a[tot].id=p;
if(tr[p].lc) dfs(tr[p].lc);
if(tr[p].rc) dfs(tr[p].rc);tr[p].lc=tr[p].rc=0;
}
inline void build(int &p,int l,int r,int op){
D=op;int mid=l+r>>1;nth_element(a+l,a+mid,a+r+1);
p=a[mid].id;tr[p].x=a[mid];
if(l<mid) build(tr[p].lc,l,mid-1,op^1);
if(r>mid) build(tr[p].rc,mid+1,r,op^1);update(p);
}
inline void seg_ins(int &p,int l,int r,int x){
if(!p) p=++owo;pp=NULL;ins(rt[p],0);
if(pp) tot=0,dfs(*pp),build(*pp,1,tot,ppop);
if(l==r) return;int mid=l+r>>1;
if(x<=mid) seg_ins(lc[p],l,mid,x);
else seg_ins(rc[p],mid+1,r,x);
}
inline bool in(int p){
return t1[0]<=tr[p].mn[0]&&t1[1]<=tr[p].mn[1]&&t2[0]>=tr[p].mx[0]&&t2[1]>=tr[p].mx[1];
}
inline bool out(int p){
return tr[p].mx[0]<t1[0]||tr[p].mx[1]<t1[1]||tr[p].mn[0]>t2[0]||tr[p].mn[1]>t2[1];
}
inline bool inn(point x){
return t1[0]<=x[0]&&t1[1]<=x[1]&&t2[0]>=x[0]&&t2[1]>=x[1];
}
inline int ask(int p){
if(!p) return 0;
if(in(p)) return tr[p].sz;
if(out(p)) return 0;
return inn(tr[p].x)+ask(tr[p].lc)+ask(tr[p].rc);
}
inline int query(int p,int l,int r,int k){
if(l==r) return l;int mid=l+r>>1,res=ask(rt[rc[p]]);
if(res>=k) return query(rc[p],mid+1,r,k);
return query(lc[p],l,mid,k-res);
}
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();
for(int i=0;i<2;++i) tr[0].mx[i]=0,tr[0].mn[i]=inf;
while(m--){
int op=read();t1[0]=read()^lastans,t1[1]=read()^lastans;
if(op==1) seg_ins(Rt,1,1e9,read()^lastans);
else{
t2[0]=read()^lastans,t2[1]=read()^lastans;int k=read()^lastans;
if(ask(rt[1])<k){puts("NAIVE!ORZzyz.");lastans=0;}
else printf("%d\n",lastans=query(Rt,1,1e9,k));
}
}return 0;
}