思路:
树链剖分模板题
#include<cstdio> #include<iostream> #include<vector> #include<cmath> #include<string> using namespace std; const int maxn = 30010; inline void qread(int &x){ x = 0; register int ch = getchar(), flag = 0; while(ch < '0' || ch > '9') { if(ch == '-') flag = 1; ch = getchar(); } while(ch >= '0' && ch <= '9') x = 10 * x + ch - 48, ch = getchar(); if(flag) x = -x; } int n, m, rt = 1; int val[maxn]; int head[maxn]; int go[maxn << 1]; int nxt[maxn << 1]; int f[maxn]; int deep[maxn]; int size[maxn]; int son[maxn]; int top[maxn]; int seg[maxn]; int rev[maxn]; int maxx[maxn << 2]; int sum[maxn << 2]; int MAX, SUM; inline void init(){ qread(n); for(register int i=1; i<n; ++i){ register int x, y; qread(x), qread(y); go[i] = y; go[i + n] = x; nxt[i] = head[x]; head[x] = i; nxt[i + n] = head[y]; head[y] = i + n; } for(int i=1; i<=n; ++i) qread(val[i]); qread(m); deep[rt] = 1; seg[0] = seg[1] = rev[1] = top[1] = 1; } void dfs1(int x){ size[x] = 1; for(register int i = head[x]; i; i = nxt[i]) if(!deep[go[i]]){ f[go[i]] = x; deep[go[i]] = deep[x] + 1; dfs1(go[i]); size[x] += size[go[i]]; if(size[go[i]] > size[son[x]]) son[x] = go[i]; } } void dfs2(int x){ if(son[x]){ seg[son[x]] = ++seg[0]; top[son[x]] = top[x]; rev[seg[0]] = son[x]; dfs2(son[x]); } for(register int i = head[x]; i; i = nxt[i]){ if(!top[go[i]]){ seg[go[i]] = ++seg[0]; rev[seg[0]] = go[i]; top[go[i]] = go[i]; dfs2(go[i]); } } } void segbuild(int l, int r, int x){ if(l==r){ sum[x] = maxx[x] = val[rev[l]]; return ; } int mid = (l + r) >> 1; segbuild(l, mid, x << 1); segbuild(mid + 1, r, x << 1 | 1); sum[x] = sum[x << 1] + sum[x << 1 | 1]; maxx[x] = max(maxx[x << 1], maxx[x << 1 | 1]); } void segchange(int l, int r, int P, int v, int x){ if(l == r){ sum[x] = maxx[x] = v; return ; } int mid = (l + r) >> 1; if(mid >= P) segchange(l, mid, P, v, x << 1); else segchange(mid + 1, r, P, v, x << 1 | 1); sum[x] = sum[x << 1] + sum[x << 1 | 1]; maxx[x] = max(maxx[x << 1], maxx[x << 1 | 1]); } void segquery(int l, int r, int L, int R, int x){ if(L <= l && R >= r){ SUM += sum[x]; MAX = max(MAX, maxx[x]); return ; } int mid = (l + r) >> 1; if(mid >= L) segquery(l, mid, L, R, x << 1); if(mid < R) segquery(mid + 1, r, L, R, x << 1 | 1); } void treeask(int x, int y){ int fx = top[x], fy = top[y]; while(fx != fy){ if(deep[fx] < deep[fy]) swap(x, y), swap(fx, fy); segquery(1, seg[0], seg[fx], seg[x], 1); x = f[fx]; fx = top[x]; } if(deep[x] > deep[y]) swap(x, y); segquery(1, seg[0], seg[x], seg[y], 1); } int main(void){ init(); dfs1(rt); dfs2(rt); segbuild(1, seg[0], 1); while(m--){ string op; cin >> op; SUM = 0, MAX = 0x80000000; if(op == "CHANGE"){ int x, y; qread(x), qread(y); segchange(1, seg[0], seg[x], y, 1); } else { int x, y; qread(x), qread(y); treeask(x, y); if(op == "QMAX") printf("%d\n", MAX); else printf("%d\n", SUM); } } }