题意:给你一个长度为$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$来更新答案
#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; }
原文地址:https://www.cnblogs.com/zzzzzzy/p/11706173.html
时间: 2024-09-28 08:27:03