翻了翻题解,只有我这么蒻不会把后缀异或和转成前缀异或和吗$QAQ$
没有想到转前缀所以蒟蒻暴力维护了后缀异或和。
首先操作离线下来,处理出添加完所有数后数列的状态,直接把所有后缀异或和插入进可持久化$trie$树里。然后倒着处理操作,这样添加就变成了删除。
删除结尾的一个数,剩下的所有后缀异或和都会异或上删掉的数。在全局维护一个$tag$,删一个数就把$tag$异或上它。在查询时只要$tag$这一位上为$1$就要反着走。
不过这题卡常,恰好我这个做法常数比较大,吸氧才能过$QAQ$。
非常神奇的一点:读入字符串用scanf
$T$得飞起,换成cin
就$A$了。数据有锅?
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 300005
using namespace std;
inline int read(){
int x=0,y=0;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return y?-x:x;
}
int siz[maxn<<6],trie[maxn<<6][2],a[maxn<<1],sum[maxn<<1],root[maxn<<1],ans[maxn],top,tag,cnt=1;
#define ls(x) trie[x][0]
#define rs(x) trie[x][1]
struct ORDER{
int s,l,r,x;
}o[maxn];
inline void update(int node){
siz[node]=siz[ls(node)]+siz[rs(node)];
}
void insert(int &node,int ol,int d,int now=25){
node=++cnt;
if(now==-1){
siz[node]=siz[ol]+1;
return;
}
bool k=d&(1<<now);
trie[node][k^1]=trie[ol][k^1];
insert(trie[node][k],trie[ol][k],d,now-1);
update(node);
}
int ask(int node,int ol,int d,int now=25){
if(now==-1)return 0;
bool k=(d&(1<<now))^(tag&(1<<now));
//异或上tag的这一位就相当于:tag这一位上为1方向改变
if(siz[trie[node][k^1]]-siz[trie[ol][k^1]]>0)return ask(trie[node][k^1],trie[ol][k^1],d,now-1)+(1<<now);
else return ask(trie[node][k],trie[ol][k],d,now-1);
}
int main(){
int n=read(),m=read();
char ss[2];
for(register int i=1;i<=n;++i)
a[i]=read();
for(register int i=1;i<=m;++i){
cin>>ss;
o[i].s=(ss[0]=='Q')+1,o[i].l=read();
if(o[i].s==1)a[++n]=o[i].l;
else o[i].r=read(),o[i].x=read();
}
for(register int i=n;i;--i)
sum[i]=sum[i+1]^a[i];
for(register int i=1;i<=n;++i)
insert(root[i],root[i-1],sum[i]);
for(register int i=m;i;--i){
if(o[i].s==1)tag^=o[i].l;//标记处理
else ans[++top]=ask(root[o[i].r],root[o[i].l-1],o[i].x);
}
while(top)printf("%d\n",ans[top--]);
}