可持久化trie处理抑或和最大值
用trie树从上往下贪心的思想查询区间抑或最大值
后缀抑或上整体转成维护前缀,方便处理修改
题目
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 600020
struct node{
int next[2],val;
}trie[maxn * 30];
int root[maxn],a[maxn],data[maxn];
int n,m,tot,xorsum;
int insert(int now,int x,int bit){
int cur = ++tot,c = (x >> (bit - 1)) & 1; //不是 x >> (bit - 1)
trie[cur].val = trie[now].val + 1;
if ( !bit ) return cur;
trie[cur].next[c] = insert(trie[now].next[c],x,bit - 1);
trie[cur].next[c ^ 1] = trie[now].next[c ^ 1];
return cur;
}
int query(int a,int b,int x,int bit){
int c = (x >> (bit - 1)) & 1,ans = 0;
if ( !bit ) return 0;
if ( (trie[trie[a].next[c ^ 1]].val - trie[trie[b].next[c ^ 1]].val) > 0 ){
ans += query(trie[a].next[c ^ 1],trie[b].next[c ^ 1],x,bit - 1);
ans += (1 << (bit - 1));
}
else{
ans += query(trie[a].next[c],trie[b].next[c],x,bit - 1);
}
/*
else{
if ( trie[trie[a].next[c ^ 1]].val - trie[trie[b].next[c ^ 1]].val ){
ans += query(trie[a].next[c ^ 1],trie[b].next[c ^ 1],x,bit - 1);
ans += (1 << (bit - 2));
}
else{
ans += query(trie[a].next[c],trie[b].next[c],x,bit - 1);
}
}*/
return ans;
}
int main(){
freopen("xor.in","r",stdin);
freopen("xor.out","w",stdout);
scanf("%d %d",&n,&m);
for (int i = 1 ; i <= n ; i++) scanf("%d",&data[i]);
a[1] = data[1];
for (int i = 2 ; i <= n ; i++) a[i] = data[i] ^ a[i - 1];
xorsum = a[n];
for (int i = 1 ; i <= n ; i++){
root[i] = insert(root[i - 1],a[i],25);
/*cout<<i<<endl;
for (int j = root[i] ; j <= tot ; j++){
cout<<j<<" "<<trie[j].val<<" next: "<<trie[j].next[0]<<" "<<trie[j].next[1]<<endl;
}
cout<<endl;*/
}
while ( m-- ){
char ch;
scanf("%s",&ch);
if ( ch == 'A' ){
scanf("%d",&data[++n]);
a[n] = a[n - 1] ^ data[n];
xorsum ^= data[n];
root[n] = insert(root[n - 1],a[n],25);
/* cout<<n<<endl;
for (int i = root[n] ; i <= tot ; i++){
cout<<i<<" "<<trie[i].val<<" next: "<<trie[i].next[0]<<" "<<trie[i].next[1]<<endl;
}
cout<<endl;*/
}
else{
int l,r,x;
scanf("%d %d %d",&l,&r,&x);
x ^= xorsum;
if ( r == 1 ) printf("%d\n",x);
else
printf("%d\n",query(root[r - 1],root[max(l - 2,0)],x,25)); //因为将后缀转化为前缀来处理,所以区间整体向左平移1,保证r,l两个端点可以被处理
}
}
return 0;
}