[BZOJ4137][FJOI2015]火星商店问题
description
有若干个\(\mbox{vector}\),支持单点\(\mbox{push_back}\),以及询问最近\(d\)次\(\mbox{push_back}\)操作中在区间\([l,r]\)内的数与\(k\)的异或最大值。
所有数\(\le10^5\)
sol
开一棵线段树,每个节点是一棵\(\mbox{Trie}\)树,这样就可以查异或最大值了。
怎么处理时间的限制呢?在\(\mbox{Trie}\)树的每个节点维护一下这个节点的最新更新时间,查询的时候如果这个最新更新时间大于一个和\(d\)有关的限制就表示可以往这个子树走,否则就不行。
然后这样子据说会\(MLE\)?
所以就把所有修改个询问都挂链挂到每个线段树的节点上,再离线线段树分治,这样空间复杂度就可以优化到\(O(n\log n)\)。
code
我不管反正我就是写在线做法。
洛谷过了,然后\(BZ\)的数据本地测过了。别的我不管qwq。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e5+5;
int n,m,tim,ch[2][N*100],val[N*100],R[N],rt[N<<2],tot,ans;
void mdf1(int &x,int p,int dep){
++tot;ch[0][tot]=ch[0][x];ch[1][tot]=ch[1][x];
val[tot]=val[x]+1;x=tot;if (!~dep) return;
mdf1(ch[(p>>dep)&1][x],p,dep-1);
}
int qry1(int x,int y,int p,int dep){
if (!~dep) return 0;int c=~(p>>dep)&1;
if (val[ch[c][x]]-val[ch[c][y]]) return qry1(ch[c][x],ch[c][y],p,dep-1)|(1<<dep);
c^=1;return qry1(ch[c][x],ch[c][y],p,dep-1);
}
void mdf2(int &x,int p,int dep,int t){
if (!x) x=++tot;val[x]=t;if (!~dep) return;
mdf2(ch[(p>>dep)&1][x],p,dep-1,t);
}
int qry2(int x,int p,int dep,int t){
if (!~dep) return 0;int c=~(p>>dep)&1;
if (val[ch[c][x]]>t) return qry2(ch[c][x],p,dep-1,t)|(1<<dep);
c^=1;return qry2(ch[c][x],p,dep-1,t);
}
void modify(int x,int l,int r,int p,int v,int t){
mdf2(rt[x],v,16,t);
if (l==r) return;int mid=l+r>>1;
if (p<=mid) modify(x<<1,l,mid,p,v,t);
else modify(x<<1|1,mid+1,r,p,v,t);
}
void query(int x,int l,int r,int ql,int qr,int v,int t){
if (l>=ql&&r<=qr) {ans=max(ans,qry2(rt[x],v,16,t));return;}
int mid=l+r>>1;
if (ql<=mid) query(x<<1,l,mid,ql,qr,v,t);
if (qr>mid) query(x<<1|1,mid+1,r,ql,qr,v,t);
}
int main(){
n=gi();m=gi();
for (int i=1;i<=n;++i) mdf1(R[i]=R[i-1],gi(),16);
for (int i=1;i<=m;++i)
if (gi()){
int l=gi(),r=gi(),v=gi(),d=gi();
ans=qry1(R[r],R[l-1],v,16);
query(1,1,n,l,r,v,tim-d);printf("%d\n",ans);
}else{
int p=gi(),v=gi();
modify(1,1,n,p,v,++tim);
}
return 0;
}