可持久化\(01Trie\)。感觉不是很会写,改天复习完主席树会再来学一次。
#include using namespace std;const int N = 600010;int s[N], rt[N], cnt[N * 25];int max_size = 1, ch[N * 25][2];void ins (int now, int pre, int x) { for (int t = 25; t >= 0; --t) { int i = (x >> t) & 1; ch[now][!i] = ch[pre][!i]; //不修改的 -> 直接连起来 ch[now][i] = ++max_size; //修改的 -> 新建节点 cnt[ch[now][i]] = cnt[ch[pre][i]] + 1; //维护一个数的个数 now = ch[now][i], pre = ch[pre][i]; } //只有在存在新节点的部分,cnt[now] 才会大于 cnt[pre]}int qry (int l, int r, int x) { int ans = 0; for (int t = 25; t >= 0; --t) { int i = (x >> t) & 1; if (cnt[ch[r][!i]] > cnt[ch[l][!i]]) { ans += (1 << t); l = ch[l][!i]; r = ch[r][!i]; } else { l = ch[l][i]; r = ch[r][i]; } //限制其不能向版本更低的地方走 //至少添加一个数, 不在i上就在!i上,不允许向cnt更低的地方走 } return ans;}int n, m, x, l, r; char opt;int main () { cin >> n >> m; rt[0] = ++max_size; ins (rt[0], 0, 0); for (int i = 1; i <= n; ++i) { scanf ("%d", &s[i]); s[i] ^= s[i - 1]; rt[i] = ++max_size; ins (rt[i], rt[i - 1], s[i]); } for (int i = 1; i <= m; ++i) { scanf (" %c", &opt); if (opt == 'A') { scanf ("%d", &x); n = n + 1; s[n] = s[n - 1] ^ x; rt[n] = ++max_size; ins (rt[n], rt[n - 1], s[n]); } else { scanf ("%d %d %d", &l, &r, &x); --l, --r; if(l <= 0) { printf ("%d\n", qry (0, rt[r], x ^ s[n])); } else { printf ("%d\n", qry (rt[l - 1], rt[r], x ^ s[n])); } } } return 0;}