[BZOJ3261][最大异或和][可持久化Trie]
题目大意:
给定一个长度为
N
的序列正整数序列和
思路:
由于异或和这种东西满足区间加减的性质,不妨设
b[i]
为位置
i
的前缀异或和,所以
注意到除了
b[p−1]
以外右边的值是唯一确定的,不妨设右边部分值为
s
,所以我们只需要维护一棵可持久化Trie(和可持久化线段树很类似),每次在
代码:
#include <cstdio>
const int Maxn = 600005;
namespace IO {
inline char get(void) {
static char buf[1000000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
inline void read(int &x) {
x = 0; static char c;
for (; !(c >= '0' && c <= '9'); c = get());
for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get());
}
inline void write(int x) {
if (!x) return (void)puts("0");
if (x < 0) putchar('-'), x = -x;
static short s[12], t;
while (x) s[++t] = x % 10, x /= 10;
while (t) putchar('0' + s[t--]);
putchar('\n');
}
inline void get(char &x) {
x = get();
while (!(x >= 'A' && x <= 'Z')) x = get();
}
};
int root[Maxn], a[Maxn], sum[Maxn], b[Maxn];
int n, m;
struct Trie {
int cnt;
int ch[Maxn << 5][2], sum[Maxn << 5];
inline int insert(int x, int val) {
int tmp, y;
tmp = y = ++cnt;
for (int i = 23; i >= 0; i--) {
ch[y][0] = ch[x][0];
ch[y][1] = ch[x][1];
sum[y] = sum[x] + 1;
int t = (val & b[i]) >> i;
x = ch[x][t];
ch[y][t] = ++cnt;
y = ch[y][t];
}
sum[y] = sum[x] + 1;
return tmp;
}
inline int query(int l, int r, int val) {
int tmp = 0;
for (int i = 23; i >= 0; i--) {
int t = (val & b[i]) >> i;
if (sum[ch[r][t ^ 1]] - sum[ch[l][t ^ 1]])
tmp += b[i], r = ch[r][t ^ 1], l = ch[l][t ^ 1];
else r = ch[r][t], l = ch[l][t];
}
return tmp;
}
} trie;
int main(void) {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
IO::read(n), IO::read(m); n++;
b[0] = 1; for (int i = 1; i < 30; i++) b[i] = b[i - 1] << 1;
for (int i = 2; i <= n; i++) IO::read(a[i]);
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] ^ a[i];
for (int i = 1; i <= n; i++) root[i] = trie.insert(root[i - 1], sum[i]);
char op;
while (m--) {
if (IO::get(op), op == 'A') {
n++; IO::read(a[n]), sum[n] = sum[n - 1] ^ a[n];
root[n] = trie.insert(root[n - 1], sum[n]);
}
else {
int l, r, x;
IO::read(l), IO::read(r), IO::read(x);
IO::write(trie.query(root[l - 1], root[r], x ^ sum[n]));
}
}
return 0;
}
完。
By g1n0st