能过捉迷藏,但过不了这题,除了前两个和后两个点是 AC 以外都是 WA。猜测是负权边导致的。
思路是线段树维护区间直径,信息合并时找出两颗子树的四个直径端点中距离最远的两个作为新的直径端点。
#include<bits/stdc++.h>
#define N 200000
#define L 20
#define int long long
#define ls id<<1,l,(l+r)>>1
#define rs id<<1|1,((l+r)>>1)+1,r
using namespace std;
struct ljb{
int en,v[2*N+5],w[2*N+5],fst[N+5],nxt[2*N+5];
inline void add(int x,int y,int z)
{
en++;
v[en]=y;
w[en]=z;
nxt[en]=fst[x];
fst[x]=en;
}
};
ljb g;
int n,q,lg2[2*N+5],dep[N+5],e[2*N+5],f[2*N+5],id,l[N+5],st[4*N+5][L+5];
string s;
inline void dfs(int x,int fa,int d)
{
dep[x]=d,e[++id]=x,l[x]=id,f[id]=l[x];
for(int i=g.fst[x];i;i=g.nxt[i])
{
int v=g.v[i];
if(v!=fa) dfs(v,x,d+g.w[i]),e[++id]=x,f[id]=l[x];
}
}
inline int LCA(int x,int y)
{
if(l[x]>l[y]) swap(x,y);
int _=lg2[l[y]-l[x]+1];
return e[min(st[l[x]][_],st[l[y]-(1<<_)+1][_])];
}
inline int dis(int x,int y)
{
if(x==0&&y==0) return -1000000000000000000ll;
if(x==0||y==0) return 0;
return dep[x]+dep[y]-2*dep[LCA(x,y)];
}
struct nd{
int x,y;
inline nd operator +(nd u)
{
nd res;res.x=0,res.y=0;
int mx=-1000000000000000000ll,tmp;
tmp=dis(x,y);
if(tmp>mx) mx=tmp,res.x=x,res.y=y;
tmp=dis(u.x,u.y);
if(tmp>mx) mx=tmp,res.x=u.x,res.y=u.y;
tmp=dis(x,u.x);
if(tmp>mx) mx=tmp,res.x=x,res.y=u.x;
tmp=dis(x,u.y);
if(tmp>mx) mx=tmp,res.x=x,res.y=u.y;
tmp=dis(y,u.x);
if(tmp>mx) mx=tmp,res.x=y,res.y=u.x;
tmp=dis(y,u.y);
if(tmp>mx) mx=tmp,res.x=y,res.y=u.y;
return res;
}
};
struct xds{
nd a[4*N+5];
inline void upd(int id,int l,int r,int x)
{
if(r<x||l>x) return;
if(l==r)
{
if(a[id].x==0) a[id].x=a[id].y=x;
else a[id].x=a[id].y=0;
return;
}
upd(ls,x),upd(rs,x);
a[id]=a[id<<1]+a[id<<1|1];
}
};
xds t;
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
lg2[0]=-1;for(int i=1;i<=2*N;i++) lg2[i]=lg2[i>>1]+1;
for(int i=1,x,y,z;i<n;i++)
cin>>x>>y>>z,g.add(x,y,z),g.add(y,x,z);
dfs(1,0,0);
memset(st,63,sizeof(st));
for(int i=1;i<=2*n-1;i++) st[i][0]=f[i];
for(int i=1;i<=L;i++)
for(int j=1;j<=2*n-1;j++)
st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
for(int i=1;i<=n;i++) t.upd(1,1,n,i);
cin>>q;
while(q--)
{
cin>>s;
if(s[0]=='C')
{
int x;
cin>>x;
t.upd(1,1,n,x);
}
else
{
int ans=dis(t.a[1].x,t.a[1].y);
if(ans==-1000000000000000000ll) cout<<"They have disappeared.\n";
else cout<<ans<<'\n';
}
}
return 0;
}/*5
1 2 1
1 3 10
2 4 100
2 5 1000*/
如有大佬调出来了,蒟蒻不胜感激!