[BZOJ 3531][SDOI 2014]旅行
动态开点线段树+树剖。
写完 编译 一遍过样例 交了 1A 这感觉还挺爽QAQ。。
#include <bits/stdc++.h> #define maxn 100010 using namespace std; int n, Q; int w[maxn], c[maxn]; //-------------------------------------------------------------------// struct Edge{ int to, next; }edge[maxn << 1]; int h[maxn], cnt; void add(int u, int v){ cnt ++; edge[cnt].to = v; edge[cnt].next = h[u]; h[u] = cnt; } //-------------------------------------------------------------------// int son[maxn], top[maxn], pos[maxn], dfs_clock, size[maxn]; int fa[maxn], dep[maxn]; void dfs1(int u){ dep[u] = dep[fa[u]] + 1; size[u] = 1; for(int i = h[u]; i; i = edge[i].next){ int v = edge[i].to; if(v == fa[u])continue; fa[v] = u; dfs1(v); size[u] += size[v]; if(size[v] > size[son[u]]) son[u] = v; } } void dfs2(int u, int tp){ pos[u] = ++ dfs_clock; top[u] = tp; if(son[u])dfs2(son[u], tp); for(int i = h[u]; i; i = edge[i].next){ int v = edge[i].to; if(v == fa[u] || v == son[u]) continue; dfs2(v, v); } } //-------------------------------------------------------------------// #define M 10000010 int root[maxn], lc[M], rc[M], mx[M], s[M], Smz; void pushup(int id){ s[id] = s[lc[id]] + s[rc[id]]; mx[id] = max(mx[lc[id]], mx[rc[id]]); } void update(int &id, int l, int r, int p, int val){ if(id == 0)id = ++ Smz; if(l == r){s[id] = val, mx[id] = val;return;} int mid = l + r >> 1; if(p <= mid)update(lc[id], l, mid, p, val); else update(rc[id], mid+1, r, p, val); pushup(id); } int Asksum(int id, int l, int r, int L, int R){ if(id == 0)return 0; if(l == L && R == r)return s[id]; int mid = l + r >> 1; if(R <= mid)return Asksum(lc[id], l, mid, L, R); if(L > mid) return Asksum(rc[id], mid+1, r, L, R); return Asksum(lc[id], l, mid, L, mid) + Asksum(rc[id], mid+1, r, mid+1, R); } int Askmx(int id, int l, int r, int L, int R){ if(id == 0)return 0; if(l == L && R == r)return mx[id]; int mid = l + r >> 1; if(R <= mid)return Askmx(lc[id], l, mid, L, R); if(L > mid) return Askmx(rc[id], mid+1, r, L, R); return max(Askmx(lc[id], l, mid, L, mid), Askmx(rc[id], mid+1, r, mid+1, R)); } int asksum(int u, int v){ int C = c[u], ret = 0; while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]]) swap(u, v); ret += Asksum(root[C], 1, n, pos[top[u]], pos[u]); u = fa[top[u]]; } if(dep[u] > dep[v])swap(u, v); ret += Asksum(root[C], 1, n, pos[u], pos[v]); return ret; } int askmx(int u, int v){ int C = c[u], ret = 0; while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]]) swap(u, v); ret = max(ret, Askmx(root[C], 1, n, pos[top[u]], pos[u])); u = fa[top[u]]; } if(dep[u] > dep[v])swap(u, v); ret = max(ret, Askmx(root[C], 1, n, pos[u], pos[v])); return ret; } int main(){ char cmd[2]; scanf("%d%d", &n, &Q); for(int i = 1; i <= n; i ++) scanf("%d%d", &w[i], &c[i]); int x, y; for(int i = 1; i < n; i ++){ scanf("%d%d", &x, &y); add(x, y), add(y, x); } dfs1(1); dfs2(1, 1); for(int i = 1; i <= n; i ++) update(root[c[i]], 1, n, pos[i], w[i]); while(Q --){ scanf("%s", cmd); scanf("%d%d", &x, &y); switch(cmd[1]){ case 'C': update(root[c[x]], 1, n, pos[x], 0), c[x] = y; update(root[y], 1, n, pos[x], w[x]); break; case 'W': update(root[c[x]], 1, n, pos[x], w[x] = y); break; case 'S': printf("%d ", asksum(x, y)); break; case 'M': printf("%d ", askmx(x, y)); break; } } return 0; }