Tree
给定一棵树,节点有点权,然后有三种操作:
一、修改1−>s1->s1−>s的路径上的点权与ttt进行按位或。
二、修改1−>s1->s1−>s的路径上的点权与ttt进行按位与。
三、查询1−>s1->s1−>s的路径上的点权异或和是否为ttt。
可以考虑树剖,然后对每一位维护一个010101线段树,然后push_uppush\_uppush_up区间111的个数即可,
对于按位或操作,如果当前位为111,则区间覆盖为111,否则不做操作。
对于按位与操作,如果当前位为000,则区间覆盖为000,否则不做操作。
整体来说只要对线段树维护一个区间覆盖lazylazylazy即可。
对于查询操作如果当前位上111的个数是奇数,说明当前位对答案有贡献。
#include <bits/stdc++.h>
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1using namespace std;const int N = 1e5 + 10;int a[N], b[N], n, m;int head[N], to[N << 1], nex[N << 1], cnt = 1;int son[N], fa[N], sz[N], dep[N], top[N], rk[N], id[N], tot;struct Tree {int sum[N << 2], lazy[N << 2];void push_up(int rt) {sum[rt] = sum[ls] + sum[rs];}void push_down(int rt, int l, int r) {if (lazy[rt] != -1) {lazy[ls] = lazy[rt], lazy[rs] = lazy[rt];if (lazy[rt]) {sum[ls] = mid - l + 1, sum[rs] = r - mid;}else {sum[ls] = 0, sum[rs] = 0;}lazy[rt] = -1;}}void build(int rt, int l, int r) {lazy[rt] = -1;if (l == r) {sum[rt] = b[rk[l]];return ;}build(lson);build(rson);push_up(rt);}void update(int rt, int l, int r, int L, int R, int v) {if (l >= L && r <= R) {lazy[rt] = v;if (v) {sum[rt] = r - l + 1;}else {sum[rt] = 0;}return ;}push_down(rt, l, r);if (L <= mid) {update(lson, L, R, v);}if (R > mid) {update(rson, L, R, v);}push_up(rt);}int query(int rt, int l, int r, int L, int R) {if (l >= L && r <= R) {return sum[rt];}push_down(rt, l, r);int ans = 0;if (L <= mid) {ans += query(lson, L, R);}if (R > mid) {ans += query(rson, L, R);}return ans;}
}tree[30];void add(int x, int y) {to[cnt] = y;nex[cnt] = head[x];head[x] = cnt++;
}void dfs1(int rt, int f) {fa[rt] = f, dep[rt] = dep[f] + 1, sz[rt] = 1;for (int i = head[rt]; i; i = nex[i]) {if (to[i] == f) {continue;}dfs1(to[i], rt);sz[rt] += sz[to[i]];if (!son[rt] || sz[to[i]] > sz[son[rt]]) {son[rt] = to[i];}}
}void dfs2(int rt, int tp) {top[rt] = tp, rk[++tot] = rt, id[rt] = tot;if (!son[rt]) {return ;}dfs2(son[rt], tp);for (int i = head[rt]; i; i = nex[i]) {if (to[i] == fa[rt] || to[i] == son[rt]) {continue;}dfs2(to[i], to[i]);}
}typedef pair<int, int> pii;pii A[110];int num;void get_interval(int s) {num = 0;while (top[s] != 1) {A[++num] = make_pair(id[top[s]], id[s]);s = fa[top[s]];}A[++num] = make_pair(id[1], id[s]);
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);scanf("%d %d", &n, &m);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);}for (int i = 1, x, y; i < n; i++) {scanf("%d %d", &x, &y);add(x, y);add(y, x);}dfs1(1, 0);dfs2(1, 1);for (int k = 0; k < 30; k++) {for (int i = 1; i <= n; i++) {b[i] = a[i] >> k & 1;}tree[k].build(1, 1, n);}for (int i = 1, op, s, t; i <= m; i++) {scanf("%d %d %d", &op, &s, &t);get_interval(s);if (op == 1) {for (int k = 0; k < 30; k++) {if (t >> k & 1) {for (int j = 1; j <= num; j++) {int l = A[j].first, r = A[j].second;tree[k].update(1, 1, n, l, r, 1);}}}}else if (op == 2) {for (int k = 0; k < 30; k++) {if (t >> k & 1) {continue;}for (int j = 1; j <= num; j++) {int l = A[j].first, r = A[j].second;tree[k].update(1, 1, n, l, r, 0);}}}else {int ans = 0;for (int k = 0; k < 30; k++) {int cur = 0;for (int j = 1; j <= num; j++) {int l = A[j].first, r = A[j].second;cur += tree[k].query(1, 1, n, l, r);}if (cur & 1) {ans |= 1 << k;}}puts(ans != t ? "YES" : "NO");}}return 0;
}