CH#56C(LCA+dfs序)
性质是:把节点dfs序以后,异象石按这个序号排序,然后相邻两两求树上距离,这些距离的和除以二就是最小斯坦纳树。
插入删除的具体操作是根据我们上述性质,用一个set维护dfn,比如插入x,则ans加上:(set里的,即之前已经插进来的)左x + x右 - 左右。
1 const int maxn = 1e5 + 5; 2 typedef set<ll> S; 3 typedef S::iterator Sit; 4 5 int n, m, t, tot, Time; 6 int head[maxn], to[maxn << 1], nxt[maxn << 1]; 7 int dfn[maxn], mp[maxn]; 8 ll val[maxn << 1], dis[maxn][20]; 9 10 int f[maxn][20], d[maxn]; 11 12 S s; 13 ll ans; 14 15 inline void add(int u, int v, ll cost) { 16 to[++tot] = v, val[tot] = cost, nxt[tot] = head[u], head[u] = tot; 17 } 18 19 inline void bfs() { 20 queue<int> Q; 21 Q.push(1), d[1] = 1; 22 23 while (!Q.empty()) { 24 int x = Q.front(); Q.pop(); 25 26 for (int i = head[x]; i; i = nxt[i]) { 27 int y = to[i]; 28 if (d[y]) continue; 29 30 d[y] = d[x] + 1; 31 dis[y][0] = val[i]; 32 f[y][0] = x; 33 34 rep(j, 1, t) { 35 f[y][j] = f[f[y][j - 1]][j - 1]; 36 dis[y][j] = dis[f[y][j - 1]][j - 1] + dis[y][j - 1]; 37 } 38 39 Q.push(y); 40 } 41 } 42 } 43 44 inline void dfs(int cur, int fa) { 45 dfn[cur] = ++Time; 46 mp[Time] = cur; 47 48 for (int i = head[cur]; i; i = nxt[i]) { 49 int v = to[i]; 50 if (v == fa) continue; 51 dfs(v, cur); 52 } 53 } 54 55 inline Sit getL(Sit it) { 56 if (it == s.begin()) return --s.end(); 57 return --it; 58 } 59 60 inline Sit getR(Sit it) { 61 if (it == --s.end()) return s.begin(); 62 return ++it; 63 } 64 65 inline ll lca(int x, int y) { 66 ll ret = 0; 67 68 if (d[x] > d[y]) swap(x, y); 69 70 irep(i, t, 0) 71 if (d[f[y][i]] >= d[x]) { 72 ret += dis[y][i]; 73 y = f[y][i]; 74 } 75 76 if (x == y) return ret; 77 78 irep(i, t, 0) 79 if (f[x][i] != f[y][i]) { 80 ret += dis[x][i] + dis[y][i]; 81 x = f[x][i], y = f[y][i]; 82 } 83 84 return ret + dis[x][0] + dis[y][0]; 85 } 86 87 int main() { 88 read(n); 89 rep(i, 1, n - 1) { 90 int u, v; 91 ll cost; 92 read(u), read(v), read(cost); 93 add(u, v, cost), add(v, u, cost); 94 } 95 96 t = (int)(log(n) / log(2)) + 1; 97 bfs(); 98 dfs(1, 0); 99 100 read(m); 101 rep(i, 1, m) { 102 char str[2]; 103 scanf("%s", str); 104 105 if (str[0] == '?') { 106 writeln(ans / 2); 107 } else { 108 int x; 109 read(x); 110 111 if (str[0] == '+') { 112 if (s.size()) { 113 Sit R = s.lower_bound(dfn[x]); 114 if (R == s.end()) R = s.begin(); 115 Sit L = getL(R); 116 117 ans += lca(mp[*L], x) + lca(x, mp[*R]) - lca(mp[*L], mp[*R]); 118 } 119 s.insert(dfn[x]); 120 } else { 121 Sit it = s.find(dfn[x]); 122 Sit L = getL(it), R = getR(it); 123 124 ans -= lca(mp[*L], x) + lca(x, mp[*R]) - lca(mp[*L], mp[*R]); 125 s.erase(it); 126 } 127 } 128 } 129 130 return 0; 131 }