我感觉就是线段树+LCA的思想了
核心还是线段树
需要注意
在标记中,一个节点的所有子孙一定都是标号小于该节点的。
https://www.luogu.com.cn/problem/P2590
洛谷例题
解答
功能变多了就会很长很长
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn = 1e5 + 7; vector<int>G[maxn]; int n; void add(int x, int y) { G[x].push_back(y); } int dep[maxn], top[maxn], id[maxn], fa[maxn], siz[maxn]; int son[maxn]; ll list[maxn];//初始编号 ll cns[maxn];//改动后用来建线段树的编号 ll sum[4 * maxn];//求和 ll mx[4 * maxn]; int dfs1(int x, int f,int d) { dep[x] = d; fa[x] = f; siz[x] = 1; int s = 0; for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == f) continue; dfs1(p, x, d + 1); siz[x] += siz[p]; if (s < siz[p]) { s = siz[p]; son[x] = p; } } return 0; }//haah int cnt; int dfs2(int x,int t) { id[x] = ++cnt; cns[cnt] = list[x]; top[x] = t; if (!son[x]) return 0; dfs2(son[x], t);//重儿子重复利用t for (int i = 0; i < G[x].size();i++) { int p = G[x][i]; if (p == fa[x] || p == son[x]) continue; dfs2(p, p);//轻儿子新建t } return 0; } int bulit(int node, int be, int en) { if (be == en) { mx[node] = cns[be]; sum[node] = cns[be]; return 0; } int l = node * 2; int r = node * 2 + 1; int mid = (be + en) / 2; bulit(l, be, mid); bulit(r, mid + 1, en); sum[node] = sum[l] + sum[r]; mx[node] = max(mx[l], mx[r]); return 0; } int update(int node, int be, int en, int i, int val) { if (be == en) { sum[node] = val; mx[node] = val; return 0; } int l = node * 2; int r = node * 2 + 1; int mid = (be + en) / 2; if (i <= mid) update(l, be, mid, i, val); else update(r, mid + 1, en, i, val); sum[node] = sum[l] + sum[r]; mx[node] = max(mx[l], mx[r]); return 0; } ll qurry_sum(int node, int be, int en, int LL, int RR) { if (LL > en || RR < be) return 0; if (LL <= be && RR >= en) { return sum[node]; } int l = node * 2; int r = node * 2 + 1; int mid = (be + en) / 2; ll val1 = qurry_sum(l, be, mid, LL, RR); ll val2 = qurry_sum(r, mid + 1, en, LL, RR); return val1 + val2; } ll qurry_max(int node, int be, int en, int LL, int RR) { if (LL > en || RR < be) return -1e10; if (LL <= be && en <= RR) { return mx[node]; } int l = node * 2; int r = node * 2 + 1; int mid = (be + en) / 2; ll val1 = qurry_max(l, be, mid, LL, RR); ll val2 = qurry_max(r, mid + 1, en, LL, RR); return max(val1, val2); } ll qrank_max(int x, int y) { ll ans = -1e18; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ll cns = qurry_max(1, 1, n, id[top[x]], id[x]); ans = max(ans, cns); x = fa[top[x]]; } //现在两个点在一个重链上了 if (dep[x] > dep[y]) swap(x, y); //x现在在y上面,id更小 ll cns = qurry_max(1, 1, n, id[x], id[y]);//注意顺序 ans = max(ans, cns); return ans; } ll qrank_sum(int x, int y) { ll ans = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ll cns = qurry_sum(1, 1, n, id[top[x]], id[x]); ans += cns; x = fa[top[x]]; } //现在两个点在一个重链上了 if (dep[x] > dep[y]) swap(x, y); //x现在在y上面,id更小 ll cns = qurry_sum(1, 1, n, id[x], id[y]);//注意顺序 ans += cns; return ans; } char op[20]; int main() { scanf("%d", &n); for (int i = 1; i < n; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); } for (int i = 1; i <= n; i++) { scanf("%lld", &list[i]); } dfs1(1, -1, 0); dfs2(1, 1); bulit(1, 1, n); int q; scanf("%d", &q); while (q--) { int x, y; scanf("%s", op); scanf("%d %d", &x, &y); ll ans = 0; if (op[1] == 'H') { update(1, 1, n, id[x], y); } else if (op[1] == 'M') { ans = qrank_max(x, y); printf("%lld ", ans); } else if (op[1] == 'S') { ans = qrank_sum(x, y); printf("%lld ", ans); } } return 0; }