bzoj3991 [SDOI2015]寻宝游戏

虚树,一直在想怎么在虚树里快速插入一个节点,其实不需要。

考虑我们要求的是什么,是按dfs序排序后的相邻关键点的距离和,于是我们直接用一个set维护当前的关键点集合,并记录当前的答案,有修改就在set里插入或删除就好了。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <set>
 7 #define N 100500
 8 using namespace std;
 9 int e=1,head[N];
10 struct edge{
11     int v,w,next;
12 }ed[N<<1];
13 int dep[N],fa[N][22],L[N],tot,n,m;
14 bool vis[N];
15 long long val[N];
16 struct cmp{
17     bool operator () (int a,int b){
18         return L[a]<L[b];
19     }
20 };
21 set<int ,cmp> s;
22 set<int ,cmp> :: iterator it;
23 void push(int u,int v,int w){
24     ed[e].v=v;ed[e].w=w;
25     ed[e].next=head[u];head[u]=e++;
26 }
27 void dfs(int x,int d){
28     dep[x]=d;L[x]=++tot;
29     for(int i=1;(1<<i)<=d;i++)
30         fa[x][i]=fa[fa[x][i-1]][i-1];
31     for(int i=head[x];i;i=ed[i].next){
32         int v=ed[i].v;
33         if(v==fa[x][0])continue;
34         fa[v][0]=x;val[v]=val[x]+ed[i].w;
35         dfs(v,d+1);
36     }
37 }
38 int getlca(int x,int y){
39     if(dep[x]<dep[y])swap(x,y);
40     for(int i=20;~i;i--)
41         if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
42     if(x==y)return x;
43     for(int i=20;~i;i--)
44         if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
45     return fa[x][0];
46 }
47 long long getdis(int x,int y){
48     return val[x]+val[y]-2*val[getlca(x,y)];
49 }
50 int size;
51 long long sum;
52 void work(int x,int v){
53     int y,z;
54     it=s.find(x);
55     if(it!=s.begin())it--,y=*it;
56     else it=s.end(),it--,y=*it;
57     it=s.find(x);it++;
58     if(it!=s.end())z=*it;
59     else it=s.begin(),z=*it;
60     sum+=v*(getdis(x,y)+getdis(x,z)-getdis(y,z));
61 }
62 void del(int x){
63     size--;vis[x]=0;
64     if(size<2)sum=0;
65     else work(x,-1);
66     s.erase(x);
67 }
68 void add(int x){
69     size++;vis[x]=1;
70     s.insert(x);
71     if(size<2)sum=0;
72     else work(x,1);
73 }
74 int main(){
75     scanf("%d%d",&n,&m);
76     for(int i=1,u,v,w;i<n;i++){
77         scanf("%d%d%d",&u,&v,&w);
78         push(u,v,w); push(v,u,w);
79     }
80     dfs(1,1);
81     int x;
82     while(m--){
83         scanf("%d",&x);
84         if(vis[x]) del(x);
85         else add(x);
86         printf("%lld\n",sum);
87     }
88     return 0;
89 }
View Code

 

posted @ 2018-03-14 15:51  Ren_Ivan  阅读(183)  评论(0编辑  收藏  举报