[FJOI2015]火星商店问题
神仙线段树分治。。。不过我不会。
这题用线段树套可持久化Trie还是能写的。
常数有点大,洛谷垫底水平。
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int rt[2000000],ch[10000000][2],tot[10000000];
int cnt,id;
il vd cp(int a,int b){ch[b][0]=ch[a][0],ch[b][1]=ch[a][1],tot[b]=tot[a];}
il vd Insert(int lst,int p){
rt[++cnt]=++id;
cp(rt[lst],rt[cnt]);
int y=rt[cnt];
for(int i=16;~i;--i){
++tot[y];
int t=(p>>i)&1;
cp(ch[y][t],++id);ch[y][t]=id;
y=ch[y][t];
}
++tot[y];
}
il int Query(int x,int y,int k){
int ans=0;
for(int i=16;~i;--i){
int t=(k>>i)&1;
if(tot[ch[y][!t]]!=tot[ch[x][!t]])ans+=1<<i,x=ch[x][!t],y=ch[y][!t];
else x=ch[x][t],y=ch[y][t];
}
return ans;
}
std::vector<std::pair<int,int> >S[400001];
#define mid ((l+r)>>1)
#define ls (x<<1)
#define rs (x<<1|1)
typedef const int& ci;
il vd update(int x,int l,int r,ci p,ci d,ci T){
Insert(S[x].back().first,d);
S[x].push_back(std::make_pair(cnt,T));
if(l==r)return;
if(p<=mid)update(ls,l,mid,p,d,T);
else update(rs,mid+1,r,p,d,T);
}
il int query(int x,int l,int r,ci L,ci R,ci k,ci d){
if(L<=l&&r<=R){
int LL=0,RR=S[x].size()-1;
while(LL<RR){
int md=(LL+RR)>>1;
if(S[x][md+1].second<d)LL=md+1;
else RR=md;
}
return Query(rt[S[x][LL].first],rt[S[x].back().first],k);
}
int ans=0;
if(L<=mid)ans=std::max(ans,query(ls,l,mid,L,R,k,d));
if(mid<R)ans=std::max(ans,query(rs,mid+1,r,L,R,k,d));
return ans;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("4585.in","r",stdin);
freopen("4585.out","w",stdout);
#endif
int n=gi(),m=gi();
for(int i=1;i<=n;++i)Insert(i-1,gi());
int T=0,opt,l,r,x,d;
for(int i=1;i<=4*n;++i)S[i].push_back(std::make_pair(0,0));
for(int i=1;i<=m;++i){
opt=gi();
if(opt==0){
x=gi(),d=gi(),++T;
update(1,1,n,x,d,T);
}else{
l=gi(),r=gi(),x=gi(),d=gi();
int ans=Query(rt[l-1],rt[r],x);
if(d)ans=std::max(ans,query(1,1,n,l,r,x,T-d+1));
printf("%d\n",ans);
}
}
return 0;
}