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 }

 

posted @ 2019-04-02 00:40  AlphaWA  阅读(260)  评论(0编辑  收藏  举报