链接
写一个 (LCT) 做法。
对于一个以 (x) 为根的 (splay) ,设 (mx_x) 为以 (x) 为根的子树中的答案,显然可以与 (ls_x,rs_x) 与虚子树中的 (mx) 取最大值。
显然只有经过 (x) 的链没有计算,我们考虑 (x) 本身,(ls_x,rs_x) 和虚子树中白点离 (x) 最远的距离,它们中任意两个相加都可以更新答案,以及虚子树中的最长链与次长链相加也可以更新答案。
如何维护它们呢?设 (lx_x) 为以 (x) 为根的 (splay) 中白点离最左端的点的最长距离,(ls_x) 中白点离 (x) 最远的距离即可通过 (rx_{ls_x}) 得出,(rx_x) 同理。
而 (lx_x) 可以由 (lx_{ls_x}) 或 (lx_{rs_x}) 与虚子树最长链加上左部分的边的总权值得到,(rx_x) 同理。
边权可以拆边或直接赋到点上维护,这里用第二种方法,常数小,但边权处理稍显复杂。
(frak{code})
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
using namespace std;
const int N=1e5+3,inf=1e9;
struct hh{
int to,nxt,w;
}e[N<<1];
int n,m,num,siz,ans,val[N],col[N],fir[N];
int fa[N],ch[N][2],vsum[N],lx[N],rx[N],mx[N],lv[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
struct heap{
priority_queue<int>q1,q2;int siz;
IL void pre(){while(q2.size()&&q1.top()==q2.top()) q1.pop(),q2.pop();}
IL void push(int x){q1.push(x),++siz;}
IL void pop(int x){q2.push(x),--siz;}
IL int top(){pre();return siz?q1.top():-inf;}
IL int ask(){
if(siz<2) return -inf;
int x=top();pop(x);
int y=top();push(x);
return x+y;
}
}q1[N],q2[N];
IL int max(int x,int y){return x>y?x:y;}
IL int min(int x,int y){return x<y?x:y;}
IL int chk(int x){return rs(fa[x])==x;}
IL int noroot(int x){return ls(fa[x])==x||rs(fa[x])==x;}
IL void pushup(int x){
vsum[x]=vsum[ls(x)]+vsum[rs(x)]+val[x],
mx[x]=max(mx[ls(x)],mx[rs(x)]),
lv[x]=ls(x)?lv[ls(x)]:val[x];
int Max=max(q1[x].top(),col[x]);
lx[x]=max(lx[ls(x)],max(lx[rs(x)]+lv[rs(x)],Max)+val[x]+vsum[ls(x)]-lv[x]),
rx[x]=max(rx[rs(x)],max(rx[ls(x)]+val[x],Max)+vsum[rs(x)]),
mx[x]=max(mx[x],max(q1[x].ask(),q2[x].top())),
mx[x]=max(mx[x],lx[rs(x)]+lv[rs(x)]+rx[ls(x)]+val[x]),
mx[x]=max(mx[x],max(Max+rx[ls(x)]+val[x],Max+lx[rs(x)]+lv[rs(x)]));
if(!col[x]) mx[x]=max(mx[x],q1[x].top());
}
IL void rotate(int x){
int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
if(noroot(y)) ch[z][chk(y)]=x;
if(w) fa[w]=y;
fa[y]=x,fa[x]=z,ch[x][k^1]=y,ch[y][k]=w;
pushup(y);
}
IL void splay(int x){
while(noroot(x)){
int y=fa[x];
if(noroot(y))
rotate(chk(x)^chk(y)?x:y);
rotate(x);
}
pushup(x);
}
IL void access(int x){
for(int y=0;x;x=fa[y=x]){
splay(x);
if(rs(x)) q1[x].push(lx[rs(x)]+lv[rs(x)]),q2[x].push(mx[rs(x)]);
if(rs(x)=y) q1[x].pop(lx[rs(x)]+lv[rs(x)]),q2[x].pop(mx[rs(x)]);
pushup(x);
}
}
IL void add(int x,int y,int z){e[++num]=(hh){y,fir[x],z},fir[x]=num;}
void dfs(int u,int f){
for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
if(v^f){
fa[v]=u,val[v]=e[i].w,dfs(v,u),
q1[u].push(lx[v]+lv[v]),q2[u].push(mx[v]);
}
pushup(u);
}
int main()
{
char op[10];int x,y,z;
siz=n=in(),lx[0]=rx[0]=mx[0]=-inf;
for(int i=1;i<n;++i)
x=in(),y=in(),z=in(),
add(x,y,z),add(y,x,z);
dfs(1,0),ans=mx[1],m=in();
while(m--){
scanf("%s",op+1);
if(op[1]=='C'){
x=in(),access(x),splay(x);
if(col[x]) col[x]=0,++siz;
else col[x]=-inf,--siz;
pushup(x),ans=mx[x];
}
else{
if(siz==1) printf("0
");
else if(!siz) printf("They have disappeared.
");
else printf("%d
",max(0,ans));
}
}
return 0;
}