用的是外层权值线段树,内层 K-D Tree 的写法。内层 K-D Tree 更新用的是二进制分组重构。
实在卡不过去,恳求大佬提供个卡常方法 /kel
#8 在本地实测 20s
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
const int Q=1e5+5;
const int B=20;
const int inf=1e9;
int n,m,k,ans;
vector<int>L(2),R(2),val(2);
namespace KDT{
int idx=0;
int cmptype;
stack<int>S;
struct Point{
vector<int>x;
inline friend bool operator<(Point A,Point B){
return A.x[cmptype]<B.x[cmptype];
}
}a[Q];
int p;
/*
notice to clear p !!!
*/
struct node{
int ch[2];
int sum;
vector<int>l,r,x;
}tr[Q<<5];
struct KDTree{
#define lc tr[i].ch[0]
#define rc tr[i].ch[1]
#define mid (l+r)/2
inline int newnode(){
if(!S.empty()){
int x=S.top();
S.pop();
return x;
}
return ++idx;
}
void build(int &i,int l,int r,int type){
if(l>r){
i=0;
return;
}
i=newnode();
if(l<r){
cmptype=type;
nth_element(a+l,a+mid,a+r+1);
}
int lst=R[type];
R[type]=a[mid].x[type];
build(lc,l,mid-1,type^1);
R[type]=lst;
lst=L[type];
L[type]=a[mid].x[type];
build(rc,mid+1,r,type^1);
L[type]=lst;
tr[i].l=a[mid].x,tr[i].r=a[mid].x,tr[i].x=a[mid].x;
if(lc){
tr[i].l[0]=min(tr[i].l[0],tr[lc].l[0]);
tr[i].l[1]=min(tr[i].l[1],tr[lc].l[1]);
tr[i].r[0]=max(tr[i].r[0],tr[lc].r[0]);
tr[i].r[1]=max(tr[i].r[1],tr[lc].r[1]);
}
if(rc){
tr[i].l[0]=min(tr[i].l[0],tr[rc].l[0]);
tr[i].l[1]=min(tr[i].l[1],tr[rc].l[1]);
tr[i].r[0]=max(tr[i].r[0],tr[rc].r[0]);
tr[i].r[1]=max(tr[i].r[1],tr[rc].r[1]);
}
tr[i].sum=r-l+1;
}
void flatten(int i){
if(!i){
return;
}
a[++p].x=tr[i].x;
S.push(i);
flatten(lc);
flatten(rc);
}
int query(int i){
if(!i){
return 0;
}
auto check1=[&](){
for(register int d=0;d<2;d++){
if(R[d]<tr[i].l[d]){
return 0;
}
if(L[d]>tr[i].r[d]){
return 0;
}
}
return 1;
};
if(!check1()){
return 0;
}
auto check2=[&](){
for(register int d=0;d<2;d++){
if(L[d]>tr[i].l[d]){
return 0;
}
if(R[d]<tr[i].r[d]){
return 0;
}
}
return 1;
};
if(check2()){
return tr[i].sum;
}
auto check3=[&](){
for(register int d=0;d<2;d++){
if(L[d]>tr[i].x[d]){
return 0;
}
if(R[d]<tr[i].x[d]){
return 0;
}
}
return 1;
};
int res=0;
if(check3()){
++res;
}
res=res+query(lc);
res=res+query(rc);
return res;
}
#undef lc
#undef rc
#undef mid
}kdt;
}
using namespace KDT;
namespace SGT{
struct node{
int ch[2];
int rt[20];
}tr[Q<<5];
int idx;
struct SGTree{
#define lc tr[i].ch[0]
#define rc tr[i].ch[1]
#define mid (l+r)/2
void modify(int &i,int l,int r,int x){
if(!i){
i=++idx;
}
p=0;
a[++p].x=val;
for(int j=0;j<B;j++){
if(!tr[i].rt[j]){
L=vector<int>(2,1);
R=vector<int>(2,n);
kdt.build(tr[i].rt[j],1,p,0);
break;
}else{
kdt.flatten(tr[i].rt[j]);
tr[i].rt[j]=0;
}
}
if(l==r){
return;
}
if(x<=mid){
modify(lc,l,mid,x);
}else{
modify(rc,mid+1,r,x);
}
}
inline int getsum(int i){
if(!i){
return 0;
}
int res=0;
for(register int j=0;j<B;j++){
if(!tr[i].rt[j]){
continue;
}
res=res+kdt.query(tr[i].rt[j]);
}
return res;
}
void query(int i,int l,int r){
if(!i){
return;
}
int val;
if(l==r){
val=getsum(i);
k=k-min(k,val);
ans=l;
return;
}
if(!lc){
query(rc,mid+1,r);
return;
}
if(!rc){
query(lc,l,mid);
return;
}
val=getsum(rc);
if(k<=val){
query(rc,mid+1,r);
}else{
k=k-val;
query(lc,l,mid);
}
}
#undef lc
#undef rc
#undef mid
}sgt;
}
using namespace SGT;
inline int read(){
int x=0,f=1;
char c=getchar();
while(!isdigit(c)){
if(c=='-'){
f=-1;
}
c=getchar();
}
while(isdigit(c)){
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
return x*f;
}
int rt;
int main(){
n=read(),m=read();
int lastans=0;
for(int i=1;i<=m;i++){
int type=read();
int v;
if(type==1){
val[0]=read()^lastans,val[1]=read()^lastans,v=read()^lastans;
sgt.modify(rt,1,inf,v);
}else if(type==2){
L[0]=read()^lastans,L[1]=read()^lastans,R[0]=read()^lastans,R[1]=read()^lastans,k=read()^lastans;
ans=inf;
sgt.query(rt,1,inf);
if(k>0){
lastans=0;
printf("NAIVE!ORZzyz.\n");
}else{
printf("%d\n",lastans=ans);
}
}
}
return 0;
}