做法:可持久化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;
}
京公网安备 11010502036488号