思路:好吧这次我们不用点分树,我们用听起来更屌的链分治。
直接把树剖成若干条重链,这样保证从任意一个点跳到根节点是不会跳超过logloglog条重链的。
然后用上链分治的常规套路:分是否在链上面的信息讨论,并将整条链的值全部统计在链顶,这样修改的时候沿着链往上跳修改logloglog次即可。
那么针对这道题可以怎么瞎搞维护呢?
考虑对每个点构建一个大根堆hih_ihi来维护它的子树去掉重儿子所在子树一位的点到它的距离的最值。
显然这个是可以从它的轻儿子们的答案转移过来的。
然后怎么维护整棵子树的最值呢?
对于每条重链我们开一棵线段树,把它们从上到下映射成一段连续的从左到右的区间,这样链顶对应最左端点,链底对应最右端点。
我们的线段树节点维护到区间最左端的最大值,到最右端的最大值,区间中相距最大的距离。
这个转移神似最大子段和,大家自己yyyyyy吧。
细节较多,详细的可以看代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
int ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ~w?ans:-ans;
}
typedef pair<int,int> pii;
const int N=1e5+5,inf=1<<28;
int n,m,siz[N],top[N],num[N],pred[N],bot[N],fa[N],hson[N],f[N],a[N],dis[N],tot=0;
bool col[N];
vector<pii>e[N];
struct deletable_heap{
priority_queue<int>a,b;
inline void push(const int&x){a.push(x);}
inline void del(const int&x){b.push(x);}
inline int top(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();return a.top();}
inline void pop(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();a.pop();}
inline int size(){return a.size()-b.size();}
inline int stop(){int tmp=top(),ret;return pop(),ret=top(),push(tmp),ret;}
inline void f(int x,int&a,int&b,int&c){
pii ret=pii(-inf,-inf);
if(!col[x])ret.fi=ret.se=0;
if(size())ret.fi=max(ret.fi,top());
if(size()>1)ret.se=max(ret.se,stop());
a=b=ret.fi,c=!col[x]?max(ret.fi,ret.fi+ret.se):ret.fi+ret.se;
}
}h[N],Ans;
inline int max(const int&a,const int&b){return a>b?a:b;}
inline int max(const int&a,const int&b,const int&c){return max(max(a,b),c);}
namespace SGT{
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
struct Node{int l,r,sum,ls,rs,ms;}T[N<<2];
inline Node operator+(const Node&a,const Node&b){
Node ret;
ret.l=a.l,ret.r=b.r;
int tmp=dis[pred[b.l]]-dis[pred[a.r]];
ret.sum=a.sum+tmp+b.sum;
ret.ls=max(a.ls,a.sum+tmp+b.ls);
ret.rs=max(b.rs,b.sum+tmp+a.rs);
ret.ms=max(a.ms,b.ms,a.rs+tmp+b.ls);
return ret;
}
inline void Set(int p){
int k=pred[T[p].l];
T[p].sum=0,h[k].f(k,T[p].ls,T[p].rs,T[p].ms);
}
inline void pushup(int p){T[p]=T[lc]+T[rc];}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r;
if(l==r)return;
build(lc,l,mid),build(rc,mid+1,r);
}
inline void update(int p,int k){
if(T[p].l==T[p].r)return Set(p);
update(k<=mid?lc:rc,k),pushup(p);
}
inline Node query(int p,int ql,int qr){
if(ql<=T[p].l&&T[p].r<=qr)return T[p];
if(qr<=mid)return query(lc,ql,qr);
if(ql>mid)return query(rc,ql,qr);
return query(lc,ql,qr)+query(rc,ql,qr);
}
#undef lc
#undef rc
#undef mid
}
void dfs1(int p){
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i].fi)==fa[p])continue;
fa[v]=p,dis[v]=dis[p]+e[p][i].se,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
void dfs2(int p,int tp){
top[p]=tp,pred[num[p]=++tot]=p,bot[tp]=p;
if(!hson[p])return;
dfs2(hson[p],tp);
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i].fi)==fa[p]||v==hson[p])continue;
dfs2(v,v);
}
}
int dfs3(int p){
for(ri x=p;x;x=hson[x]){
for(ri i=0,v;i<e[x].size();++i){
if((v=e[x][i].fi)==hson[x]||v==fa[x])continue;
h[x].push(dfs3(v)+e[x][i].se);
}
SGT::update(1,num[x]);
}
SGT::Node tmp=SGT::query(1,num[p],num[bot[p]]);
return Ans.push(tmp.ms),tmp.ls;
}
inline void update(int p){
while(p){
int ft=fa[top[p]],tp=top[p];
SGT::Node tmp=SGT::query(1,num[top[p]],num[bot[top[p]]]);
Ans.del(tmp.ms);
if(ft)h[ft].del(tmp.ls+dis[tp]-dis[ft]);
SGT::update(1,num[p]);
tmp=SGT::query(1,num[top[p]],num[bot[top[p]]]);
Ans.push(tmp.ms);
if(ft)h[ft].push(tmp.ls+dis[tp]-dis[ft]);
p=ft;
}
}
char s[2];
int main(){
n=read();
for(ri i=1,u,v,w;i<n;++i){
u=read(),v=read(),w=read();
e[u].push_back(pii(v,w));
e[v].push_back(pii(u,w));
}
dfs1(1),dfs2(1,1);
SGT::build(1,1,n);
dfs3(1);
for(ri all=n,tt=read();tt;--tt){
scanf("%s",s);
if(s[0]=='A'){
if(all>1)cout<<Ans.top()<<'\n';
else if(all==1)puts("0");
else puts("They have disappeared.");
}
else{
int x=read();
col[x]^=1;
if(col[x])--all;
else ++all;
update(x);
}
}
return 0;
}