image.png
    image.png

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. typedef long long LL;
    4. const int N = 100010, M = N*2;
    5. int n, m, idx;
    6. vector<int> T[N];
    7. //id[i]: 原数组每个点的编号
    8. //nw[i]: dfs序列中第i个点的编号
    9. int id[N], nw[N], w[N];
    10. //top[i]: i点所在重链的顶点编号
    11. //son[i]: i点的重儿子
    12. int dep[N], sz[N], top[N], fa[N], son[N];
    13. struct node {
    14. int l, r;
    15. LL add, sum;
    16. };
    17. struct SegTree {
    18. node tr[N*4];
    19. void inline pushup(int u) {
    20. tr[u].sum = tr[u<<1].sum+tr[u<<1|1].sum;
    21. }
    22. void inline eval(node& t, int add) {
    23. t.sum += add*(t.r-t.l+1);
    24. t.add += add;
    25. }
    26. void inline pushdown(int u) {
    27. if (tr[u].add) {
    28. eval(tr[u<<1], tr[u].add);
    29. eval(tr[u<<1|1], tr[u].add);
    30. tr[u].add = 0;
    31. }
    32. }
    33. void build(int u, int l, int r) {
    34. tr[u] = {l, r, 0, nw[r]};
    35. if (l == r) return;
    36. int mid = l+r>>1;
    37. build(u<<1, l, mid);
    38. build(u<<1|1, mid+1, r);
    39. pushup(u);
    40. }
    41. void update(int u, int l, int r, int k) {
    42. if (l<=tr[u].l && r>=tr[u].r) {
    43. eval(tr[u], k);
    44. return;
    45. }
    46. pushdown(u);
    47. int mid = tr[u].l+tr[u].r>>1;
    48. if (l <= mid)
    49. update(u<<1, l, r, k);
    50. if (r > mid)
    51. update(u<<1|1, l, r, k);
    52. pushup(u);
    53. }
    54. LL query(int u, int l, int r) {
    55. if (l <= tr[u].l && r >= tr[u].r)
    56. return tr[u].sum;
    57. pushdown(u);
    58. int mid = tr[u].l+tr[u].r>>1;
    59. LL res = 0;
    60. if (l <= mid)
    61. res += query(u<<1, l, r);
    62. if (r > mid)
    63. res += query(u<<1|1, l, r);
    64. return res;
    65. }
    66. }ST;
    67. void dfs1(int u, int father, int depth) {
    68. dep[u] = depth, fa[u] = father, sz[u] = 1;
    69. for (int i = 0; i < T[u].size(); i++) {
    70. int j = T[u][i];
    71. if (j == father)
    72. continue;
    73. dfs1(j, u, depth + 1);
    74. sz[u] += sz[j];
    75. if (sz[son[u]] < sz[j])
    76. son[u] = j;
    77. }
    78. }
    79. void dfs2(int u, int t) {
    80. //t: 当前点所在重链的顶点
    81. id[u] = ++idx, nw[idx] = w[u], top[u] = t;
    82. if (!son[u])
    83. return;
    84. //优先搜索重儿子
    85. dfs2(son[u], t);
    86. for (int i = 0; i < T[u].size(); i++) {
    87. int j = T[u][i];
    88. if (j==fa[u] || j==son[u])
    89. continue;
    90. //搜轻儿子,轻儿子重链顶点就是本身
    91. dfs2(j, j);
    92. }
    93. }
    94. void update_path(int u, int v, int k) {
    95. //若两个点不在同一重链中
    96. while (top[u] != top[v]) {
    97. if (dep[top[u]] < dep[top[v]])
    98. swap(u, v);
    99. ST.update(1, id[top[u]], id[u], k);
    100. u = fa[top[u]];
    101. }
    102. if (dep[u] < dep[v])
    103. swap(u, v);
    104. ST.update(1, id[v], id[u], k);
    105. }
    106. LL query_path(int u, int v) {
    107. LL res = 0;
    108. while (top[u] != top[v]) {
    109. if (dep[top[u]] < dep[top[v]]) swap(u, v);
    110. res += ST.query(1, id[top[u]], id[u]);
    111. u = fa[top[u]];
    112. }
    113. if (dep[u] < dep[v]) swap(u, v);
    114. res += ST.query(1, id[v], id[u]);
    115. return res;
    116. }
    117. void update_tree(int u, int k) {
    118. ST.update(1, id[u], id[u]+sz[u]-1, k);
    119. }
    120. LL query_tree(int u) {
    121. return ST.query(1, id[u], id[u]+sz[u]-1);
    122. }
    123. int main() {
    124. scanf("%d", &n);
    125. for (int i = 1; i <= n; i++)
    126. scanf("%d", &w[i]);
    127. for (int i = 0; i < n-1; i++) {
    128. int u, v;
    129. scanf("%d%d", &u, &v);
    130. T[u].push_back(v);
    131. T[v].push_back(u);
    132. }
    133. //第一遍dfs找出每个点的重儿子
    134. dfs1(1, -1, 1);
    135. //第二遍dfs求dfs序
    136. dfs2(1, 1);
    137. ST.build(1, 1, n);
    138. scanf("%d", &m);
    139. while (m--) {
    140. int t, u, v, k;
    141. scanf("%d%d", &t, &u);
    142. if (t == 1) {
    143. scanf("%d%d", &v, &k);
    144. update_path(u, v, k);
    145. } else if (t == 2) {
    146. scanf("%d", &k);
    147. update_tree(u, k);
    148. } else if (t == 3) {
    149. scanf("%d", &v);
    150. printf("%lld\n", query_path(u, v));
    151. } else {
    152. printf("%lld\n", query_tree(u));
    153. }
    154. }
    155. return 0;
    156. }