Description
给定一棵树,根节点为1,给出两种操作:
- 查询x节点当前的val
- 给出x, val, 修改x节点及其子树的值,注意修改过程是随着深度+-+-进行交替的
Solution
首先处理出dfs序,随后单点查询,区间修改可以用差分树状数组来维护。
注意到区间修改的过程是随着深度而改变的,那么不妨开两个树状数组,一个维护奇数层的修改,另一个维护偶数层的修改,不改变原来的权值,只对树状数组进行修改。那么最后的答案就是原来的权值,加上当前奇偶层的修改数,即
Code
#include <bits/stdc++.h> using namespace std; typedef long long ll; using namespace std; const int N = 5e5 + 5; int depth[N], a[N]; struct Edge { int v, nextz; }edge[N << 1]; int tot, in[N], out[N], head[N], cnt; void addedge(int u, int v) { edge[cnt].v = v; edge[cnt].nextz = head[u]; head[u] = cnt++; } void dfs(int u, int par) { in[u] = ++tot; for(int i = head[u]; ~i; i = edge[i].nextz) { int v = edge[i].v; if(v == par) continue; depth[v] = depth[u] + 1; dfs(v, u); } out[u] = tot; } ll T[N][2]; int lowbit(int x) { return x & (-x); } void update(int x, int add, int id) { while(x < N) { T[x][id] += add; x += lowbit(x); } } int query(int x, int id) { ll res = 0; while(x) { res += T[x][id]; x -= lowbit(x); } return res; } int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int n, m; cin >> n >> m; memset(head, -1, sizeof(head)); for(int i = 1; i <= n; i++) cin >> a[i]; for(int i = 1; i <= n - 1; i++) { int u, v; cin >> u >> v; addedge(u, v); addedge(v, u); } depth[1] = 1; dfs(1, -1); while(m--) { int op, x, val; cin >> op >> x; if(op == 1) { cin >> val; if(depth[x] & 1) { update(in[x], val, 1); update(out[x] + 1, -val, 1); update(in[x], -val, 0); update(out[x] + 1, val, 0); } else { update(in[x], val, 0); update(out[x] + 1, -val, 0); update(in[x], -val, 1); update(out[x] + 1, val, 1); } } else { if(depth[x] & 1) cout << a[x] + query(in[x], 1) << '\n'; else { cout << a[x] + query(in[x], 0) << '\n'; } } } return 0; }