模仿主席树的思路打了一个代码。
每一个点插入以后合并,查询的时候要注意一下边界问题就好。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 6e5 + 10, M = N * 32;
int cnt, trie[M][2], rt[N];
int n, m;
void insert(int p, int x) {
for (int i = 30; i >= 0; i--)
trie[p][x >> i & 1] = ++cnt, p = cnt;
}
void merge(int &x, int y) {
if (!x) { x = y; return;}
if (!y) return;
merge(trie[x][0], trie[y][0]);
merge(trie[x][1], trie[y][1]);
}
int calc(int l, int r, int x) {
int ans = 0;
for (int i = 30; i >= 0; i--) {
int p = x >> i & 1;
if (trie[l][p ^ 1] != trie[r][p ^ 1]) ans += (1 << i), l = trie[l][p ^ 1], r = trie[r][p ^ 1];
else if (trie[r][p]) l = trie[l][p], r = trie[r][p];
else break;
}
return ans;
}
int main() {
rt[0] = ++cnt, insert(rt[0], 0);
cin >> n >> m; int now = 0;
for (int i = 1; i <= n; i++) {
int x; scanf("%d", &x); now ^= x;
rt[i] = ++cnt, insert(rt[i], now);
merge(rt[i], rt[i - 1]);
}
while (m--) {
char s[5]; scanf("%s", s);
if (s[0] == 'A') {
int x; scanf("%d", &x); now ^= x;
rt[++n] = ++cnt; insert(rt[n], now);
merge(rt[n], rt[n - 1]);
}
else {
int l, r, x; scanf("%d%d%d", &l, &r, &x);
x ^= now;
if (r == 1) { printf("%d\n", x); continue;}
int ans = calc(l > 1 ? rt[l - 2] : rt[l - 1], rt[r - 1], x);
printf("%d\n", l > 1 ? ans : max(ans, x));
}
}
return 0;
}