P6225 [eJOI2019]异或橙子 树状数组 异或 位运算
给定一个数组a。
对数组a进行操作
1.修改a[i] = j
2.对区间 L , R 求每个子区间的异或和。
容易发现若 R - L 为奇数,每个数的贡献是偶数次,答案为0
若不为奇数,则奇偶相同的位数会贡献奇数次,其他贡献偶数次,即 al ^ al+2 ^ al+4 .....ar
可以用树状数组维护异或和。
由于与奇偶相关,考虑建立两颗树状数组。
注意代码中update的时候是用a[i] ^ j 来更新,这里利用了异或的性质 来实现往上更新节点。
int a[maxn]; int n; struct BIT { int c[maxn]; int ask(int x) { int ans = 0; for (; x ; x -= x & -x) ans ^= c[x]; return ans; } void update(int x, int y) { for (; x <= n ; x += x & -x) c[x] ^= y; } }; BIT b[2]; int main() { int q; n = readint(), q = readint(); for (int i = 1; i <= n; i++) { int x = readint(); b[i & 1].update(i, x); a[i] = x; } while (q--) { int x = readint(); int i = readint(); int j = readint(); if (x == 1) { b[i & 1].update(i, a[i] ^ j), a[i] = j; } else { if ((i + j) & 1) puts("0"); else printf("%d\n", b[(i & 1)].ask(j) ^ b[(i & 1)].ask(i - 1)); } } }