做法:可持久化01tire
思路:
令s[i] = a[1] ^ a[2] ^ … a[i-1] ^ a[i]
则a[p] xor a[p+1] xor … xor a[N] xor x 相当于 s[N] ^ x ^ s[p-1]
s[N] ^ x 每次可以看成一个固定值 v提前算出来, 则相当于 求 l-1 <= p-1 <= r-1 使得 v 与 s[p-1]异或最大
s[p-1]的二进制最高位开始到最低位的每一个数字尽量与v的二进制对应位相反就可以保证异或出来最大。
s的每个版本可以看成是持久化的trie记录下来。
对持久化trie的每个节点额外维护一个信息max_id,表示其所属的持久化版本,显然一个节点的max_id等于其子节点中最大的版本号(因为子节点要么是连向之前的版本,要么创建了该节点后再创建子节点)。 如果一个节点的max_id 小于l-1,说明这个节点是s[l-1]插入之前就已经创建出来的节点,不应该考虑在内。
代码
#include <bits/stdc++.h> using namespace std; #define pb push_back #define mp(aa,bb) make_pair(aa,bb) #define _for(i,b) for(int i=(0);i<(b);i++) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define per(i,b,a) for(int i=(b);i>=(a);i--) #define mst(abc,bca) memset(abc,bca,sizeof abc) #define X first #define Y second #define lowbit(a) (a&(-a)) typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; typedef long double ld; const int N=6e5+10; const int INF=0x3f3f3f3f; const int mod=1e9+7; const double eps=1e-6; int s[N]; struct Trie { int root[N],nex[N*32][2],cnt=0; int max_id[N*32]; void insert(int k) { int p,q; if(!k) p=0,q=root[k]; else p=root[k-1],q=root[k]; max_id[q]=k; for (int i = 30; i >= 0; i--) { int c=s[k]>>i&1; if(p) nex[q][c^1]=nex[p][c^1]; nex[q][c] = ++cnt; max_id[nex[q][c]]=k; p=nex[p][c],q=nex[q][c]; } } int query(int p,int l,int x) { for (int i = 30; i >= 0; i--) { int c = x>>i&1; if(max_id[nex[p][c^1]]>=l) p=nex[p][c^1]; else p=nex[p][c]; } return x^s[max_id[p]]; } } t; int main() { ios::sync_with_stdio(0);cin.tie(0); #ifdef DEBUG freopen("F:/laji/1.in", "r", stdin); // freopen("F:/laji/2.out", "w", stdout); #endif int n,m;cin>>n>>m; t.max_id[0]=-1; //-1表示不存在 // t.root[0]=++t.cnt; // t.insert(0); rep(i,1,n){ int a;cin>>a; s[i]=s[i-1]^a; t.root[i]=++t.cnt; t.insert(i); } while(m--){ char op;cin>>op; if(op=='A'){ int x;cin>>x; t.root[++n]=++t.cnt; s[n]=s[n-1]^x; t.insert(n); } else{ int l,r,x;cin>>l>>r>>x; cout<<t.query(t.root[r-1],l-1,s[n]^x)<<"\n"; } } return 0; }