解析
大结论题…
实在是不知道这题和虚树有半毛钱关系吗…
引理
给出一个按照dfs排列的点集S={a1,a2…ak}
它们的极小联通子树的边权和的二倍等于∑dis(a1,a2)+dis(a2,a3)+...+dis(ak−1,ak)+dis(ak,a1)\sum dis(a_1,a_2)+dis(a_2,a_3)+...+dis(a_k-1,a_k)+dis(a_k,a_1)∑dis(a1,a2)+dis(a2,a3)+...+dis(ak−1,ak)+dis(ak,a1)
证明
按照本题的情景说吧,似乎更好理解一些
最优的路径是一个环,所以其实从哪个点开始都是可以的
所以我们其实就是决定一个先去哪里的问题
…不难发现按照dfs序走肯定是不劣的(或者说,就是最优的)
这什么垃圾证明
然后…本题就做完了…
写个lca板子,再维护个set指针找找前驱后继加加特判即可
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e5+100;
const int mod=998244353;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int n,m;struct node{int to,nxt;ll w;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y,int w){p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;return;
}int pl[N][18];
ll dep[N];
int siz[N],pos[N],tim;
void init(int x,int f){siz[x]=1;pos[x]=++tim;pl[x][0]=f;for(int k=1;pl[x][k-1];k++) pl[x][k]=pl[pl[x][k-1]][k-1];for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;dep[to]=dep[x]+p[i].w;init(to,x);siz[x]+=siz[to];}return;
}
inline int Lca(int x,int y){if(pos[x]<=pos[y]&&pos[y]<=pos[x]+siz[x]-1) return x;for(int k=17;k>=0;k--){int o=pl[x][k];if(!o||(pos[o]<=pos[y]&&pos[y]<=pos[o]+siz[o]-1)) continue;x=o;}return pl[x][0];
}
inline ll dis(int x,int y){int lca=Lca(x,y);return dep[x]+dep[y]-2*dep[lca];
}struct id{int x;
};
bool operator < (const id a,const id b){return pos[a.x]<pos[b.x];
}
bool operator > (const id a,const id b){return b<a;
}
set<id>s;
set<id>::iterator it1,it2;
int num;
ll ans(0);int main() {
#ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);
#endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<n;i++){int x=read(),y=read(),w=read();addline(x,y,w);addline(y,x,w);}init(1,0);for(int t=1;t<=m;t++){int x=read();id o=(id){x};if(s.count(o)){s.erase(o),num--;if(num==0){printf("0\n");continue;}id fir=*s.begin();if(fir>o){it1=s.end();it1--;it2=s.begin();}else if(s.upper_bound(o)==s.end()){it1=s.end();it1--;it2=s.begin();}else{it1=it2=s.upper_bound(o);it1--;}int pre=(*it1).x,suf=(*it2).x;ans-=dis(pre,x)+dis(suf,x)-dis(pre,suf);}else{if(num==0){s.insert(o);num++;printf("0\n");continue;}id fir=(*s.begin());//printf("ok x=%d\n",fir.x);if(fir>o){it1=s.end();it1--;it2=s.begin();}else if(s.upper_bound(o)==s.end()){it1=s.end();it1--;it2=s.begin();}else{it1=it2=s.upper_bound(o);it1--;}int pre=(*it1).x,suf=(*it2).x;ans+=dis(pre,x)+dis(suf,x)-dis(pre,suf);//printf("pre=%d suf=%d\n",pre,suf);s.insert(o);num++;}printf("%lld\n",ans);}return 0;
}
/*
*/