3991: [SDOI2015]寻宝游戏

3991: [SDOI2015]寻宝游戏

https://www.lydsy.com/JudgeOnline/problem.php?id=3991

分析:

  虚树+set。

  要求树上许多点之间的路径的总长的2倍。就是虚树。

  结论:如果将所有的点按dfs序拍好,答案就是相邻点之间的路径长度的和*2。所以这个可以按dfn维护一个set,每次操作查找前驱后继。

代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<cctype>
  7 #include<set>
  8 #include<vector>
  9 #include<queue>
 10 #include<map>
 11 using namespace std;
 12 typedef long long LL;
 13 
 14 inline int read() {
 15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 17 }
 18 
 19 const int INF = 1e9;
 20 const int N = 100005;
 21 
 22 int head[N], nxt[N << 1], to[N << 1], len[N << 1], En;
 23 int deth[N], bel[N], siz[N], son[N], fa[N], id[N], dfn[N], TimeIndex;
 24 LL dis[N];
 25 bool vis[N];
 26 LL tmp, Ans;
 27 set<int> s; 
 28 set<int> :: iterator it;
 29 
 30 void add_edge(int u,int v,int w) {
 31     ++En; to[En] = v; len[En] = w; nxt[En] = head[u]; head[u] = En;
 32     ++En; to[En] = u; len[En] = w; nxt[En] = head[v]; head[v] = En;
 33 }
 34 
 35 void dfs1(int u) {
 36     deth[u] = deth[fa[u]] + 1;
 37     for (int i=head[u]; i; i=nxt[i]) {
 38         int v = to[i];
 39         if (v == fa[u]) continue; 
 40         dis[v] = dis[u] + len[i];
 41         fa[v] = u;
 42         dfs1(v);
 43         siz[u] += siz[v];
 44         if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;
 45     }
 46 }
 47 
 48 void dfs2(int u,int top) {
 49     bel[u] = top;
 50     dfn[u] = ++TimeIndex; id[TimeIndex] = u;
 51     if (!son[u]) return ;
 52     dfs2(son[u], top);
 53     for (int i=head[u]; i; i=nxt[i]) {
 54         int v = to[i];
 55         if (v != fa[u] && v != son[u]) dfs2(v, v);
 56     }
 57 }
 58 
 59 int LCA(int u,int v) {
 60     while (bel[u] != bel[v]) {
 61         if (deth[bel[u]] < deth[bel[v]]) swap(u, v);
 62         u = fa[bel[u]];
 63     }
 64     return deth[u] < deth[v] ? u : v;
 65 }
 66 
 67 LL getdis(int x,int y) {
 68     int lca = LCA(x, y);
 69     return dis[x] + dis[y] - (dis[lca] * 2);
 70 }
 71 
 72 void ins(int x) {
 73     int L = *(--s.lower_bound(dfn[x]));
 74     int R = *(s.upper_bound(dfn[x]));
 75     if (L != -INF) Ans += getdis(id[L], x);
 76     if (R != INF) Ans += getdis(id[R], x);
 77     if (L != -INF && R != INF) Ans -= getdis(id[L], id[R]);
 78     s.insert(dfn[x]); vis[x] = 1;
 79 }
 80 
 81 void del(int x) {
 82     s.erase(dfn[x]); vis[x] = 0;
 83     int L = *(--s.lower_bound(dfn[x]));
 84     int R = *(s.upper_bound(dfn[x]));
 85     if (L != -INF) Ans -= getdis(id[L], x);
 86     if (R != INF) Ans -= getdis(id[R], x);
 87     if (L != -INF && R != INF) Ans += getdis(id[L], id[R]);
 88 }
 89 
 90 int main() {
 91     int n = read(), Q = read();
 92     for (int i=1; i<n; ++i) {
 93         int u = read(), v = read(), w = read();
 94         add_edge(u, v, w);
 95     }
 96     dfs1(1);
 97     dfs2(1, 1);
 98     
 99     s.insert(-INF), s.insert(INF);
100     
101     while (Q--) {
102         tmp = 0;
103         int x = read();
104         if (!vis[x]) ins(x);
105         else del(x);
106         if (s.size() > 3) {
107             it = s.begin(); 
108             int L = *(++it);
109             it = s.end(); 
110             int R = *(--(--it));
111             tmp = getdis(id[L], id[R]);
112         }
113         printf("%lld
",Ans + tmp);
114     }
115     return 0;
116 }
原文地址:https://www.cnblogs.com/mjtcn/p/9707262.html