https://www.luogu.org/recordnew/show/5120068
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1e5 + 10; #define gc getchar() #define lson jd << 1 #define rson jd << 1 | 1 #define LL long long LL ans; int n, Ti, tim_clock, now = 1; int head[N], tree[N], bef[N << 2], deep[N], data[N], fa[N], topp[N], siz[N], son[N], L[N], R[N]; struct Node{ int u, v, nxt; }G[N << 2]; struct Node_2{ int l, r; LL w, f; }T[N << 4]; inline int read(){ int x = 0, f = 1; char c = gc; while(c < ‘0‘ || c > ‘9‘) {if(c == ‘-‘) f = -1; c = gc;} while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = gc; return x * f; } inline void swap(int & x, int & y){ x ^= y; y ^= x; x ^= y; } inline void add(int u, int v){ G[now].v = v; G[now].nxt = head[u]; head[u] = now ++; } void dfs_find_son(int u, int f, int dep){ fa[u] = f; deep[u] = dep; siz[u] = 1; for(int i = head[u]; ~ i; i = G[i].nxt){ int v = G[i].v; if(v != f) { dfs_find_son(v, u, dep + 1); siz[u] += siz[v]; if(siz[v] > siz[son[u]]) son[u] = v; } } } void dfs_to_un(int u, int tp){ topp[u] = tp; L[u] = ++ tim_clock; tree[u] = tim_clock; bef[tim_clock] = u; if(!son[u]){R[u] = tim_clock; return ;} dfs_to_un(son[u], tp); for(int i = head[u]; ~ i; i = G[i].nxt){ int v = G[i].v; if(v != fa[u] && v != son[u]) dfs_to_un(v, v); } R[u] = tim_clock; } void down(int jd){ int F = T[jd].f; T[lson].w += ((T[lson].r - T[lson].l + 1) * F); T[lson].f += F; T[rson].w += ((T[rson].r - T[rson].l + 1) * F); T[rson].f += F; T[jd].f = 0; } void build_tree(int l, int r, int jd){ T[jd].l = l; T[jd].r = r; if(l == r){T[jd].w = data[bef[l]]; return ;} int mid = (l + r) >> 1; build_tree(l, mid, lson); build_tree(mid + 1, r, rson); T[jd].w = T[lson].w + T[rson].w; } void Poi_G(int l, int r, int jd, int x, int yj){ if(l == r) {T[jd].w += yj; return ;} if(T[jd].f) down(jd); int mid = (l + r) >> 1; if(x <= mid) Poi_G(l, mid, lson, x, yj); else Poi_G(mid + 1, r, rson, x, yj); T[jd].w = T[lson].w + T[rson].w; } void Sec_G(int l, int r, int jd, int x, int y, int yj){ if(x <= l && r <= y) {T[jd].w += ((r - l + 1) * yj); T[jd].f += yj; return ;} if(T[jd].f) down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_G(l, mid, lson, x, y, yj); if(y > mid) Sec_G(mid + 1, r, rson, x, y, yj); T[jd].w = T[lson].w + T[rson].w; } void Sec_A(int l, int r, int jd, int x, int y){ if(x <= l && r <= y) {ans += T[jd].w; return ;} if(T[jd].f) down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_A(l, mid, lson, x, y); if(y > mid) Sec_A(mid + 1, r, rson, x ,y); } inline LL Sec_A_I(int x, int y){ int tp1 = topp[x], tp2 = topp[y]; LL answer = 0; while(tp1 != tp2){ if(deep[tp1] < deep[tp2]) swap(x, y), swap(tp1, tp2); ans = 0; Sec_A(1, n, 1, tree[tp1], tree[x]); answer += ans; x = fa[tp1]; tp1 = topp[x]; } ans = 0; if(deep[x] < deep[y]) swap(x, y); Sec_A(1, n, 1, tree[y], tree[x]); answer += ans; return answer; } void debug(){ for(int i = 1; i <= n; i ++) cout << tree[i] << " "; cout << endl; exit(0); } int main() { n = read(); Ti = read(); for(int i = 1; i <= n; i ++) data[i] = read(); for(int i = 1; i <= n; i ++) head[i] = -1; for(int i = 1; i < n ; i ++){ int u = read(), v = read(); add(u, v); add(v, u); } dfs_find_son(1, 0, 1); dfs_to_un(1, 1); build_tree(1, n, 1); while(Ti --){ int how = read(); if(how == 1){int x = read(), a = read(); Poi_G(1, n, 1, tree[x], a);} else if(how == 2) {int x = read(), a = read(); Sec_G(1, n, 1, L[x], R[x], a);} else {int x = read(); printf("%lld\n", Sec_A_I(x, 1));} } return 0; } /* 5 5 1 2 3 4 5 1 2 1 4 2 3 2 5 3 3 1 2 1 3 5 2 1 2 3 3 */