题目大意:一棵树,支持三个操作,
$CHANGE;u;t:$ 把结点$u$的权值改为$t$
$QMAX;u;v:$ 询问从点$u$到点$v$的路径上的节点的最大权值
$QSUM;u;v:$ 询问从点$u$到点$v$的路径上的节点的权值和
题解:裸的树链剖分
卡点:线段树区间修改我不知道哪根筋搭错了,写了$l;==;r$(应为$L;leq;l;&&;R;geq;r$)
C++ Code:
#include <cstdio> #define maxn 30010 using namespace std; const int inf = 0x3f3f3f3f; int n, m; int w[maxn], V[maxn << 2], M[maxn << 2]; inline int max(int a, int b) {return a > b ? a : b;} void swap(int &a, int &b) {a ^= b ^= a ^= b;} void update(int rt) { V[rt] = V[rt << 1] + V[rt << 1 | 1]; M[rt] = max(M[rt << 1], M[rt << 1 | 1]); } void build(int rt, int l, int r) { if (l == r) { V[rt] = M[rt] = w[l]; return ; } int mid = l + r >> 1; build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r); update(rt); } void add(int rt, int l, int r, int p, int num) { if (l == r) { V[rt] = M[rt] = num; return ; } int mid = l + r >> 1; if (p <= mid) add(rt << 1, l, mid, p, num); else add(rt << 1 | 1, mid + 1, r, p, num); update(rt); } int askS(int rt, int l, int r, int L, int R) { if (L <= l && R >= r) { return V[rt]; } int mid = l + r >> 1, ans = 0; if (L <= mid) ans = askS(rt << 1, l, mid, L, R); if (R > mid) ans = ans + askS(rt << 1 | 1, mid + 1, r, L, R); return ans; } int askM(int rt, int l, int r, int L, int R) { if (L <= l && R >= r) { return M[rt]; } int mid = l + r >> 1, ans = -inf; if (L <= mid) ans = askM(rt << 1, l, mid, L, R); if (R > mid) ans = max(ans, askM(rt << 1 | 1, mid + 1, r, L, R)); return ans; } int head[maxn], cnt; struct Edge { int to, nxt; } e[maxn << 1]; void addE(int a, int b) { e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt; } int fa[maxn], sz[maxn], son[maxn], dep[maxn]; int top[maxn], dfn[maxn], idx; void dfs1(int rt) { sz[rt] = 1; for (int i = head[rt]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa[rt]) { dep[v] = dep[rt] + 1; fa[v] = rt; dfs1(v); if (!son[rt] || sz[v] > sz[son[rt]]) son[rt] = v; sz[rt] += sz[v]; } } } void dfs2(int rt) { dfn[rt] = ++idx; int v = son[rt]; if (v) top[v] = top[rt], dfs2(v); for (int i = head[rt]; i; i = e[i].nxt) { v = e[i].to; if (v != son[rt] && v != fa[rt]) { top[v] = v; dfs2(v); } } } int queryS(int x, int y) { int ans = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ans += askS(1, 1, n, dfn[top[x]], dfn[x]); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); ans += askS(1, 1, n, dfn[x], dfn[y]); return ans; } int queryM(int x, int y) { int ans = -inf; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ans = max(ans, askM(1, 1, n, dfn[top[x]], dfn[x])); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); ans = max(ans, askM(1, 1, n, dfn[x], dfn[y])); return ans; } int main() { scanf("%d", &n); for (int i = 1; i < n; i++) { int a, b; scanf("%d%d", &a, &b); addE(a, b); addE(b, a); } dep[1] = 1; dfs1(1); top[1] = 1; dfs2(1); for (int i = 1; i <= n; i++) { scanf("%d", &w[dfn[i]]); } build(1, 1, n); scanf("%d", &m); while (m --> 0) { char op[10]; int x, y; scanf("%s%d%d", op, &x, &y); if (op[1] == 'M') { printf("%d ", queryM(x, y)); } if (op[1] == 'S') { printf("%d ", queryS(x, y)); } if (op[1] == 'H') { add(1, 1, n, dfn[x], y); } } return 0; }