题意:问树上最远白色点对,带修改
考虑点分治,每次分治时找到每棵子树深度最大的一个白点,用最大的两个统计一下即可.然后建立出点分树
考虑暴力一点,在每个点开两个堆
第一个堆插入这个重心管辖的一坨树所有白点到分治树上这个点父亲的距离
第二个堆插入所有点分治树上孩子的堆顶,这样我们就可以对于每个分治重心,找到分属两棵子树的深度最大的两个白点,即这个点堆的最大和次大值
注意一开始对于每一个重心要在自己第二个堆里把自己插入(因为自己也是百点,而且没有统计)
然后要记录答案的话就还要再开一个堆
修改就只要再点分树上从自己的重心往根走,然后维护一下那些堆即可,注意判断条件特别多
复杂度是 O(nlog2n) O ( n log 2 n ) 的,修改搞一个可以删除的堆就好了
但是特别注意,这道题有负边,所以堆空堆顶不是 0 0 而是
然后这题是 [ZJOI2007]Hide [ Z J O I 2007 ] H i d e 捉迷藏的加强版
一些实现的细节看代码吧(这题还可以树剖,会快一些)
#include<bits/stdc++.h>
#define fp(i,a,b) for(int i=a,I=b;i<=I;++i)
#define go(i,u) for(int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool chkmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void sd(T&x){
char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45)y=-1;x=c^48;
while(c=gc(),47<c&&c<58)x=(x<<1)+(x<<3)+(c^48);x*=y;
}
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
template<class T>inline void we(T x){
if(x<0)sr[++C]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
if(C>1<<20)Ot();
}
inline void ge(){strcat(sr,"They have disappeared.\n");C+=23;}
const int N=1e5+5,inf=1e9;
typedef int arr[N];
struct eg{int nx,to,w;}e[N<<1];
struct Hp{
priority_queue<int>s,t;int sz;
inline void pop(int x){t.push(x);--sz;}
inline void push(int x){s.push(x);++sz;}
inline void pre(){while(t.size()&&s.top()==t.top())s.pop(),t.pop();}
inline int top(){return pre(),sz?s.top():-inf;}
inline int len(){
if(sz<2)return 0;
int x=top();pop(x);
int y=top();push(x);
return max(x+y,0);
}
inline void op(int x,int col){col?pop(x):push(x);}
}a[N],b[N],ans;
int n,m,ce,rt,tot,Sum,Top;arr S,fi,fx,fa,Fa,sz,son,col,top,len,dep,vis;
void dfs(int u){
dep[u]=dep[fa[u]]+(sz[u]=1);
go(i,u)if(v^fa[u]){
fa[v]=u,len[v]=len[u]+e[i].w,
dfs(v),sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void dfs(int u,int t){
top[u]=t;if(son[u])dfs(son[u],t);
go(i,u)if(v^fa[u]&&v^son[u])dfs(v,v);
}
inline int lca(int u,int v){
for(;top[u]^top[v];dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]]);
return dep[u]<dep[v]?u:v;
}
inline int dis(int u,int v){return len[u]+len[v]-(len[lca(u,v)]<<1);}
void gr(int u,int fa){
fx[u]=0,sz[u]=1;S[++Top]=u;
go(i,u)if(!vis[v]&&v^fa)gr(v,u),sz[u]+=sz[v],chkmax(fx[u],sz[v]);
chkmax(fx[u],Sum-sz[u]);if(fx[u]<fx[rt])rt=u;
}
int sol(int u){
int p=Fa[u],son;vis[u]=1;b[u].push(0);
if(p)fp(i,1,Top)a[u].push(dis(p,S[i]));
go(i,u)if(!vis[v]){
Sum=sz[v],gr(v,Top=rt=0),Fa[rt]=u,son=sol(rt);
b[u].push(a[son].top());
}return ans.push(b[u].len()),u;
}
inline void mdy(int x,int cl){
int l1=b[x].len(),l2,s1,s2;b[x].op(0,cl);
if(l1^(l2=b[x].len()))ans.pop(l1),ans.push(l2);
for(int u=x,p=Fa[x];p;p=Fa[u=p]){
s1=a[u].top(),a[u].op(dis(p,x),cl),s2=a[u].top();
if(s1==s2)continue;
l1=b[p].len();if(s1!=-inf)b[p].pop(s1);if(s2!=-inf)b[p].push(s2);
l2=b[p].len();if(l1^l2)ans.pop(l1),ans.push(l2);
}
}
inline void add(int u,int v,int w){e[++ce]=eg{fi[u],v,w};fi[u]=ce;}
int main(){
#ifndef ONLINE_JUDGE
file("s");
#endif
sd(n);int u,v,w;fx[0]=N;tot=n;
fp(i,2,n)sd(u),sd(v),sd(w),add(u,v,w),add(v,u,w);
dfs(1),dfs(1,1),Sum=n;gr(1,0),sol(rt);sd(m);
while(m--){
char c;while(c=gc(),c<'A');
if(c=='A')
tot?we(tot==1?0:ans.top()):ge();
else{
sd(u);tot+=col[u]?1:-1;
col[u]^=1,mdy(u,col[u]);
}
}
return Ot(),0;
}