大概是一道树链剖分的裸题。可以看出如果不是查询相同宗教的这一点,就和普通的树链剖分毫无两样了。所以针对每一个宗教都单独开一棵线段树,变成单点修改+区间查询。只不过宗教数目很多,空间消耗太大所以只能开一棵总的再动态开点。
#include <bits/stdc++.h> using namespace std; #define maxn 200500 #define maxm 2000000 int n, q, cnp = 1, cnt, tot, root[maxn], name[maxn], head[maxn], w[maxn], c[maxn]; struct node { int id, size, fa, dep, hson, gra; }P[maxn]; struct edge { int to, last; }E[maxn]; struct tree { int sum, ext, lson, rson; }T[maxm]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); } while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar(); return x * k; } void add(int x, int y) { E[cnp].to = y, E[cnp].last = head[x], head[x] = cnp ++; } struct Segament_Tree { int query1(int p, int l, int r, int L, int R) { if(l <= L && r >= R) return T[p].sum; if(l > R || r < L) return 0; int mid = (L + R) >> 1; return query1(T[p].lson, l, r, L, mid) + query1(T[p].rson, l, r, mid + 1, R); } int query2(int p, int l, int r, int L, int R) { if(l <= L && r >= R) return T[p].ext; if(l > R || r < L) return 0; int mid = (L + R) >> 1; return max(query2(T[p].lson, l, r, L, mid), query2(T[p].rson, l, r, mid + 1, R)); } void update(int &p, int L, int R, int x, int w) { if(!p) p = ++ cnt; if(L == R) { T[p].sum = T[p].ext = w; return; } int mid = (L + R) >> 1; if(x <= mid) update(T[p].lson, L, mid, x, w); else update(T[p].rson, mid + 1, R, x, w); T[p].sum = T[T[p].lson].sum + T[T[p].rson].sum; T[p].ext = max(T[T[p].lson].ext, T[T[p].rson].ext); } }ST[maxn]; struct Heavy_Light_Decomposition { int dfs(int u) { P[u].size = 1; for(int i = head[u]; i; i = E[i].last) { int v = E[i].to; if(v == P[u].fa) continue; P[v].dep = P[u].dep + 1, P[v].fa = u; dfs(v); P[u].size += P[v].size; if(P[v].size > P[P[u].hson].size) P[u].hson = v; } } int dfs2(int u, int anc) { P[u].id = ++ tot, P[u].gra = anc, name[tot] = u; if(P[u].hson) dfs2(P[u].hson, anc); for(int i = head[u]; i; i = E[i].last) { int v = E[i].to; if(v == P[u].hson || v == P[u].fa) continue; dfs2(v, v); } } void update1(int x, int r) { ST[c[x]].update(root[c[x]], 1, tot, P[x].id, 0); ST[r].update(root[r], 1, tot, P[x].id, w[x]); c[x] = r; } void update2(int x, int t) { ST[c[x]].update(root[c[x]], 1, tot, P[x].id, t); w[x] = t; } void query1(int x, int y) { int tx = P[x].gra, ty = P[y].gra; int r = c[x]; int ans = 0; while(tx != ty) { if(P[tx].dep < P[ty].dep) swap(x, y), swap(tx, ty); ans += ST[r].query1(root[r], P[tx].id, P[x].id, 1, tot); x = P[tx].fa, tx = P[x].gra; } if(P[x].dep < P[y].dep) swap(x, y), swap(tx, ty); ans += ST[r].query1(root[r], P[y].id, P[x].id, 1, tot); printf("%d\n", ans); } void query2(int x, int y) { int tx = P[x].gra, ty = P[y].gra; int r = c[x]; int ans = 0; while(tx != ty) { if(P[tx].dep < P[ty].dep) swap(x, y), swap(tx, ty); ans = max(ans, ST[r].query2(root[r], P[tx].id, P[x].id, 1, tot)); x = P[tx].fa, tx = P[x].gra; } if(P[x].dep < P[y].dep) swap(x, y), swap(tx, ty); ans = max(ans, ST[r].query2(root[r], P[y].id, P[x].id, 1, tot)); printf("%d\n", ans); } }HLD; int main() { n = read(), q = read(); for(int i = 1; i <= n; i ++) w[i] = read(), c[i] = read(); for(int i = 1; i < n; i ++) { int x = read(), y = read(); add(x, y), add(y, x); } HLD.dfs(1), HLD.dfs2(1, 1); for(int i = 1; i < maxn; i ++) root[i] = ++ cnt; for(int i = 1; i <= n; i ++) ST[c[i]].update(root[c[i]], 1, tot, P[i].id, w[i]); for(int i = 1; i <= q; i ++) { string s; cin >> s; int x = read(), y = read(); if(s[0] == ‘C‘) { if(s[1] == ‘C‘) HLD.update1(x, y); else HLD.update2(x, y); } else { if(s[1] == ‘S‘) HLD.query1(x, y); else HLD.query2(x, y); } } return 0; }