解析
见到动态维护最远点对,不难想到利用 set
维护最大值和次大值,每个点维护两个 set
的杂技做法。
但是问题是…T了啊。
咋办嘞。
一个在本题至关重要的 trick:利用两个堆来支持访问最大值和删除
具体也很好理解:当删除的时候,就向第二个堆 push
一个删除元素,每次访问的时候先把原堆和删除堆堆顶一样的元素弹掉即可。
支持了删除,剩下的就简单了。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define OK printf("ok\n")
#define debug(...) fprintf(stderr,__VA_ARGS__)
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;
}
const int N=2e5+100;
const int inf=1e9+100;
int n,m;
struct node{int to,nxt;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt;return;
}
int dep[N],q[N<<1],tot,pl[N];
void dfs0(int x,int f){dep[x]=dep[f]+1;q[++tot]=x;pl[x]=tot;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;dfs0(to,x);q[++tot]=x;}return;
}
int Min(int x,int y){return dep[x]<dep[y]?x:y;
}
int lg[N<<1],mn[N<<1][20],mi[20];
void init(){dfs0(1,0);lg[0]=-1;for(int i=1;i<=tot;i++) lg[i]=lg[i>>1]+1;mi[0]=1;for(int i=1;i<=lg[tot];i++) mi[i]=mi[i-1]<<1;for(int i=1;i<=tot;i++) mn[i][0]=q[i];for(int k=1;k<=lg[tot];k++){for(int i=1;i+mi[k]-1<=tot;i++) mn[i][k]=Min(mn[i][k-1],mn[i+mi[k-1]][k-1]);}return;
}
inline int Lca(int x,int y){x=pl[x];y=pl[y];if(x>y) swap(x,y);int k=lg[y-x+1];//printf(" k=%d\n",k);return Min(mn[x][k],mn[y-mi[k]+1][k]);
}
inline int Dis(int x,int y){int lca=Lca(x,y);//printf("(%d %d) lca=%d dis=%d\n",x,y,lca,dep[x]+dep[y]-2*dep[lca]);return dep[x]+dep[y]-2*dep[lca];
}
vector<int>f[2][N];
int w[N],top[N];
int rt,mnn,siz[N],S,son[N];
bool vis[N];
int o;
void findrt(int x,int f){siz[x]=1;son[x]=0;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f||vis[to]) continue;findrt(to,x);siz[x]+=siz[to];son[x]=max(son[x],siz[to]);}son[x]=max(son[x],S-siz[x]);if(mnn>son[x]){mnn=son[x];rt=x;}return;
}
int tim;
int solve(int x,int nS){//if(tim%1000==0) debug("%d\n",x);//printf("??\n");S=nS;mnn=inf;findrt(x,0);x=rt;vis[x]=1;siz[x]=nS+1;f[0][x].resize(siz[x]+1);f[1][x].resize(siz[x]+1);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(vis[to]) continue;int tmp=solve(to,nS-son[to]);top[tmp]=x;}return x;
}
struct Set{priority_queue<int>q,d;inline bool empty(){return q.size()==d.size();}inline int size(){return q.size()-d.size();}inline void upd(){while(!d.empty()&&q.top()==d.top()) q.pop(),d.pop();}inline int top(){ upd();return q.top();}inline void del(int x){d.push(x);return;}inline void pop(){upd();q.pop();} inline void ins(int x){q.push(x);return;}inline int sec(){upd();int x=top();pop();int y=top();ins(x);return y;}
};
Set s0[N],s1[N],ans;
inline int calc(int x){return s0[x].top()+s0[x].sec();
}
void ins(int x,int w){if(s0[x].size()>=2) ans.del(calc(x));s0[x].ins(w);if(s0[x].size()>=2) ans.ins(calc(x));return;
}
void era(int x,int w){if(s0[x].size()>=2) ans.del(calc(x));s0[x].del(w);if(s0[x].size()>=2) ans.ins(calc(x));return;
}
int op[N],num;
void add(int x){++num;//printf("\nadd:%d\n",x);ins(x,0);for(int i=x;top[i];i=top[i]){if(!s1[i].empty()) era(top[i],s1[i].top());s1[i].ins(Dis(x,top[i]));ins(top[i],s1[i].top());}return;
}
void del(int x){--num;era(x,0);for(int i=x;top[i];i=top[i]){era(top[i],s1[i].top());s1[i].del(Dis(x,top[i]));if(!s1[i].empty()) ins(top[i],s1[i].top());}return;
}
signed main(){
#ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);
#endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();for(int i=1;i<n;i++){int x=read(),y=read();addline(x,y);addline(y,x);}init(); solve(1,n);//for(int i=1;i<=n;i++) printf("i=%d top=%d\n",i,top[i]);for(int i=1;i<=n;i++) add(i);m=read();char c;for(int i=1;i<=m;i++){scanf(" %c",&c);if(c=='G'){if(!ans.empty()) printf("%d\n",ans.top());else if(num) printf("0\n");else printf("-1\n");}else{int x=read();if(op[x]) add(x);else del(x);op[x]^=1;}}return 0;
}
/*
*/