题意:给你一个长度为$n$的数组,定义函数$f(l,r)=a_{l} \oplus a_{l+1} \oplus…\oplus a_{r}$,$F(l,r)=f(l,l)\oplus f(l,l+1)\oplus …\oplus f(l,r)\oplus f(l+1,l+1)\oplus …f(l+1,r)\oplus …\oplus f(r,r)$,有两种操作,第一种将数组中某个元素$a[x]$变为$y$,第二种计算$F(l,r)$的值。

思路:打表后发现只有当$l$和$r$同时为奇数或者偶数时$F(l,r)$才不为$0$,其他情况下$F(l,r)$都为$0$,并且$F(l,r)=a[l]\oplus a[l+2]\oplus …\oplus a[r-2]\oplus a[r]$,由于涉及到修改和查询两种操作,所以用线段树来维护,每个结点维护两个值:$w$表示区间内奇数项异或的结果,$ww$表示区间内偶数项异或的结果。

初始建树时

  • 当前项为奇数项,则输入$tree[k].w$的值,同时令$tree[k].ww=0$
  • 当前项为偶数项,则输入$tree[k].ww$的值,同时令$tree[k].w=0$

修改操作时

  • 需要修改的项为奇数项,则对$tree[k].w$进行修改
  • 需要修改的项为偶数项,则对$tree[k].ww$进行修改

查询操作时

  • 如果$l$为奇数,则用$ans=ans\oplus tree[k].w$来更新答案
  • 如果$l$为偶数,则用$ans=ans\oplus tree[k].ww$来更新答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <cstdio>

using namespace std;

const int N = 100010;

struct node {
int l, r, w, ww;
};

int a, b, x, y, ans;
node tree[4 * N];

void build(int k, int lef, int rig)
{
tree[k].l = lef, tree[k].r = rig;
if (tree[k].l == tree[k].r) {
if (0 == tree[k].l % 2) {
tree[k].w = 0, scanf("%d", &tree[k].ww);
}
else {
tree[k].ww = 0, scanf("%d", &tree[k].w);
}
return;
}
int mid = (lef + rig) / 2;
build(k * 2, lef, mid); build(k * 2 + 1, mid + 1, rig);
tree[k].w = tree[k * 2].w ^ tree[k * 2 + 1].w;
tree[k].ww = tree[k * 2].ww ^ tree[k * 2 + 1].ww;
}

void change_point(int k)
{
if (tree[k].l == tree[k].r) {
if (tree[k].l % 2 == 0) tree[k].ww = y;
else tree[k].w = y;
return;
}
int mid = (tree[k].l + tree[k].r) / 2;
if (x <= mid) change_point(2 * k);
else change_point(2 * k + 1);
tree[k].w = tree[2 * k].w ^ tree[2 * k + 1].w;
tree[k].ww = tree[2 * k].ww ^ tree[2 * k + 1].ww;
}

void ask_interval(int k)
{
if (tree[k].l >= a && tree[k].r <= b) {
if (0 == a % 2) ans ^= tree[k].ww;
else ans ^= tree[k].w;
return;
}
int mid = (tree[k].l + tree[k].r) / 2;
if (a <= mid) ask_interval(2 * k);
if (b > mid) ask_interval(2 * k + 1);
}

int main()
{
int T, t, n, q, icas = 0;
scanf("%d", &T);
while (T--) {
printf("Case #%d:\n", ++icas);
scanf("%d%d", &n, &q), build(1, 1, n);
while (q--) {
scanf("%d", &t);
if (0 == t) {
scanf("%d%d", &x, &y);
change_point(1);
}
else {
ans = 0, scanf("%d%d", &a, &b);
if (a % 2 == b % 2) ask_interval(1);
printf("%d\n", ans);
}
}
}
return 0;
}