最大异或和
可持久化Trie的又一个板子。
插入很好说,直接用insert就可以了。查询其实也还好,我们知道异或有一些好用的性质,比如:
\[A\oplus A=0
\]
所以令
\[s_i=a_1\oplus a_2\oplus\cdots\oplus a_i
\]
则有
\[a_l\oplus a_{l+1}\oplus\cdots\oplus a_r=s_{l-1}\oplus s_r
\]
所以要求
\[a[p]\oplus a[p+1]\oplus\cdots\oplus a[N]\oplus x(p\in[l,r])
\]
的最大值,就是要求
\[s_{p-1}\oplus s_N\oplus x(p\in[l,r])
\]
的最大值。后面的部分是确定不变的,所以问题就变成了一个可持久化Trie上跑01Trie求异或和最大值的板子了。(打那么多公式只是因为新学了一个Latex很兴奋)
其它便没有什么了。要注意的就是当l为1时查询区间会覆盖到0号位置,需要特殊处理一下。代码:
#include<cstdio>
//#define zczc
const int N=600010;
const int S=32;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline bool op(){
char w=getchar();
while(w!='A'&&w!='Q')w=getchar();
return w=='A';
}
int m,n;
int root[N],cnt;
struct node{
int ch[2],data;
}t[N*S];
inline void insert(int pl,int val){
int x=root[pl-1];int y=root[pl]=++cnt;
for(int i=S-1;i>=0;i--){
int now=((val>>i)&1);
t[y].ch[!now]=t[x].ch[!now];
t[y].ch[now]=++cnt;
y=t[y].ch[now],x=t[x].ch[now];
t[y].data=pl;
}
}
inline int work(int l,int x,int val){
int an=0;
for(int i=S-1;i>=0;i--){
an<<=1;int now=((val>>i)&1);
int want=t[x].ch[!now];
if(want!=0&&t[want].data>=l)an++,x=want;
else x=t[x].ch[now];
}
return an;
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);read(n);
int s1,s2,s3,num=0,all=0;
insert(++num,0);
while(m--){read(s1);all^=s1;insert(++num,all);}
while(n--){
if(op()){read(s1);all^=s1;insert(++num,all);}
else{
read(s1);read(s2);read(s3);
printf("%d\n",work(s1,root[s2],all^s3));
}
}
return 0;
}
一如既往,万事胜意