传送门biu~
可持久化Trie树。
设
bi
为1到i的异或和,则相当于求
max(bp−1xorbnxorx)
。每次向Trie树中加入
bi
。在每次加一个数的时候把Trie树的这条链的每个点权加一。查询L到R区间时相当于查询
bL−1
到
bR−1
之间的最优解。用Trie树的第R-1个版本减去第L-2个版本,如果一个点的点权大于零就说明这个点存在,反之则不存在。贪心查询最大异或和。
在序列首添加一个0会更好处理。
#include<bits/stdc++.h>
using namespace std;
int n,m,now;
struct Node{
Node *ch[2];
int sum;
Node();
}*null=new Node,*root[600005];
Node :: Node(){
ch[0]=ch[1]=null;
sum=0;
}
void build(Node *x,Node *&y,int v,int d){
y=new Node();
y->sum=x->sum+1;
if(d<0) return;
int to=v>>d&1;
y->ch[to^1]=x->ch[to^1];
build(x->ch[to],y->ch[to],v,d-1);
}
int Query(Node *x,Node *y,int v,int d){
if(d<0) return 0;
int to=v>>d&1;
int tmp=y->ch[to^1]->sum - x->ch[to^1]->sum;
if(tmp>0) return (1<<d) + Query(x->ch[to^1],y->ch[to^1],v,d-1);
else return Query(x->ch[to],y->ch[to],v,d-1);
}
int main(){
null->ch[0]=null->ch[1]=null;
scanf("%d%d",&n,&m);++n;
root[0]=new Node();
build(root[0],root[1],0,24);
for(int i=2;i<=n;++i){
int x;
scanf("%d",&x);
now^=x;
build(root[i-1],root[i],now,24);
}
char opt[3];
while(m--){
scanf("%s",opt);
if(opt[0]=='A'){
int x;
scanf("%d",&x);
now^=x;
++n;
build(root[n-1],root[n],now,24);
}
else{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
printf("%d\n",Query(root[x-1],root[y],now^k,24));
}
}
return 0;
}