Deal with the heavy son first in dfs1
BZOJ Portal: Click to open the link
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cctype> using namespace std; const int inf = 0x7f7f7f7f, maxn = 30007; #define ls p<<1 #define rs p<<1|1 struct edge { int v, nxt; }e[maxn << 1]; int head[maxn], eid = 0, siz[maxn], dep[maxn], fa[maxn], top[maxn], l[maxn], tot, val[maxn]; int sum[maxn << 2], n, q, maxx[maxn << 2],son[maxn]; /* p adjacency list siz subtree size dep node depth fa parent node top heavy chain head l is dfs order */ void insert(int u, int v) { e[++eid].v = v; e[eid].nxt = head[u]; head[u] = eid; e [++ eid] .v = u; e [eid] .nxt = head [v]; head [v] = eid; } char cmd[10]; void dfs1(int u) { you [u] = 1; int i,v; for (i = head[u]; i; i = e[i].nxt) { if (!siz[v = e[i].v]) { dep[v] = dep[u] + 1; fa [v] = u; dfs1(v); you [u] + = you [v]; if (you [v]> you [last [u]]) son[u] = v; } } } void dfs2(int u, int t) { l[u] = ++tot; top[u] = t; int i,v; if (son[u] != 0) dfs2(son[u], t); for (i = head[u]; i; i = e[i].nxt) { v = e [i] .v; if (dep[v]>dep[u] && v != son[u]) dfs2(v, v); } } void pushup(int p) { sum[p] = sum[ls] + sum[rs]; maxx[p] = max(maxx[ls], maxx[rs]); } void modify(int p, int l, int r, int x, int c) { if (l == r) { sum[p] = maxx[p] = c; return; } int mid = (l + r) >> 1; if (x <= mid) modify(ls, l, mid, x, c); else modify(rs, mid + 1, r, x, c); pushup(p); } int querysum (int p, int l, int r, int x, int y) { if (x <= l&&r <= y) return sum[p]; int mid = (l + r) >> 1, res = 0; if (x <= mid) res += querysum(ls, l, mid, x, y); if (y > mid) res += querysum(rs, mid + 1, r, x, y); return res; } int querymax (int p, int l, int r, int x, int y) { if (x <= l&&r <= y) return maxx[p]; int mid = (l + r) >> 1, res = -inf; //Point weight is -30000~30000 if (x <= mid) res = max(res, querymax(ls, l, mid, x, y)); if (y > mid) res = max(res, querymax(rs, mid + 1, r, x, y)); return res; } int getsum(int x, int y) { int res = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); res += querysum(1, 1, n, l[top[x]], l[x]); x = fa[top[x]]; } if (l[x] > l[y]) swap(x, y); res + = querysum (1, 1, n, l [x], l [y]); return res; } int getmax(int x, int y) { int res = -inf; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); res = max(res, querymax(1, 1, n, l[top[x]], l[x])); x = fa[top[x]]; } if (l[x] > l[y]) swap(x, y); res = max(res, querymax(1, 1, n, l[x], l[y])); return res; } you and; inline int read() { int s = 0, f = 1; char c = getchar(); while (c<'0' || c>'9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0'&&c <= '9') { s = s * 10 + c - '0'; c = getchar(); } return s*f; } int main() { n = read(); int i,v; for (i = 1; i < n; i++) { u = read(); v = read(); insert(u, v); } for (i = 1; i <= n; i++) val[i] = read(); dfs1 (1); dfs2(1, 1); for (int i = 1; i <= n; i++) modify(1, 1, n, l[i], val[i]); q = read(); char c,j=0; for (int i = 1; i <= q; i++) { scanf("%s" , cmd); u = read(); v = read(); switch (cmd[1]) { case 'H': val[u] = v; modify(1, 1, n, l[u], v); break; case 'M': printf("%d\n", getmax(u, v)); break; default: printf("%d\n", getsum(u, v)); } } return 0; }