树链剖分固然可以搞。
但还有另一种做法,可以看出,增加一个节点的权值会对以它为根的整棵子树都有影响,相当于给整棵子树增加一个值。
而给以某一节点 x 为根的子树增加一个权值也会影响当前子树,节点 y 所增加的值为 dis[y] * z - (dis[x] - 1) * z,每个节点都会增加 -(dis[x] - 1) * z ,
询问时只用加上 dis[y] * y 和当前节点 y 的权值。
给整棵子树增加一个权值可以用 dfs 序 + 线段树搞, dis 数组可以预处理出来。
——代码

1 #include <cstdio> 2 #include <cstring> 3 #define LL long long 4 #define root 1, 1, n 5 #define ls now << 1, l, mid 6 #define rs now << 1 | 1, mid + 1, r 7 8 using namespace std; 9 10 const int MAXN = 100001; 11 int n, m, cnt, tot; 12 int head[MAXN], next[MAXN << 1], to[MAXN << 1], tid[MAXN], size[MAXN]; 13 LL a[MAXN << 2], b[MAXN << 2], val[MAXN], dis[MAXN]; 14 15 inline void add(int x, int y) 16 { 17 to[cnt] = y; 18 next[cnt] = head[x]; 19 head[x] = cnt++; 20 } 21 22 inline void dfs(int u) 23 { 24 int i, v; 25 tid[u] = ++tot; 26 size[u] = 1; 27 for(i = head[u]; i != -1; i = next[i]) 28 { 29 v = to[i]; 30 if(!size[v]) 31 { 32 dis[v] = dis[u] + 1; 33 dfs(v); 34 size[u] += size[v]; 35 } 36 } 37 } 38 39 inline void push_down(int now) 40 { 41 a[now << 1] += a[now]; 42 a[now << 1 | 1] += a[now]; 43 b[now << 1] += b[now]; 44 b[now << 1 | 1] += b[now]; 45 a[now] = b[now] = 0; 46 } 47 48 inline void update(LL x, LL y, int ql, int qr, int now, int l, int r) 49 { 50 if(ql <= l && r <= qr) 51 { 52 a[now] += x; 53 b[now] += y; 54 return; 55 } 56 push_down(now); 57 int mid = (l + r) >> 1; 58 if(ql <= mid) update(x, y, ql, qr, ls); 59 if(mid < qr) update(x, y, ql, qr, rs); 60 } 61 62 inline LL query(int u, int x, int now, int l, int r) 63 { 64 if(l == r) return dis[u] * a[now] + b[now]; 65 push_down(now); 66 int mid = (l + r) >> 1; 67 if(x <= mid) return query(u, x, ls); 68 else return query(u, x, rs); 69 } 70 71 int main() 72 { 73 int i, x, z; 74 LL y; 75 scanf("%d %d", &n, &m); 76 for(i = 1; i <= n; i++) scanf("%lld", &val[i]); 77 memset(head, -1, sizeof(head)); 78 for(i = 1; i < n; i++) 79 { 80 scanf("%d %d", &x, &y); 81 add(x, y); 82 add(y, x); 83 } 84 dis[1] = 1; 85 dfs(1); 86 for(i = 1; i <= n; i++) update(0, val[i], tid[i], tid[i] + size[i] - 1, root); 87 for(i = 1; i <= m; i++) 88 { 89 scanf("%d %d", &z, &x); 90 if(z == 1) 91 { 92 scanf("%lld", &y); 93 update(0, y, tid[x], tid[x] + size[x] - 1, root); 94 } 95 else if(z == 2) 96 { 97 scanf("%lld", &y); 98 update(y, -((dis[x] - 1) * y), tid[x], tid[x] + size[x] - 1, root); 99 } 100 else printf("%lld ", query(x, tid[x], root)); 101 } 102 return 0; 103 }