传送中的动态点分治。
就是在点分治的同时把分治树建立出来,然后每个节点用数据结构维护节点内的内容。
这道题用了三个set,(貌似也可以用6个堆,每个set用一个ins堆和一个del堆来代替),一个维护当前rt的答案,就是当前点作为这一块联通块的根时往下能到达黑点的长度。一个维护当前rt对于它在分治树上的父亲的贡献,也就是当前rt里每一个点和当前rt在分治树上的父亲间的距离(用lca求)。再全局开一个set维护每个rt中可以算作答案的最大值和次大值的和。
Achen不仅智力低下码力也这么低下。。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
const int N=100007,M=500007;
typedef long long LL;
using namespace std;
int n,Q,clo[N];
char o[10];
template<typename T>void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
if(ch==‘-‘) f=-1,ch=getchar();
for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f;
}
int ecnt,fir[N],nxt[N<<1],to[N<<1];
void add(int u,int v) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
}
int f[N][17],R[N];
int get_lca(int x,int y) {
if(R[x]<R[y]) swap(x,y);
int rs=0;
for(int i=16;i>=0;i--)
if(R[f[x][i]]>=R[y]) {
x=f[x][i];
rs+=(1<<i);
}
if(x==y) return rs;
for(int i=16;i>=0;i--)
if(f[x][i]!=f[y][i]) {
x=f[x][i]; y=f[y][i];
rs+=(1<<(i+1));
}
return rs+2;
}
void dfs1(int x,int fa) {
f[x][0]=fa;
R[x]=R[fa]+1;
for(int i=1;i<17;i++) f[x][i]=f[f[x][i-1]][i-1];
for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
dfs1(to[i],x);
}
}
int nowsz,nf[N],vis[N],rt,sz[N],mxson[N],g[N][2];
void get_root(int x,int fa) {
sz[x]=mxson[x]=1;
for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa) {
get_root(to[i],x);
sz[x]+=sz[to[i]];
mxson[x]=max(mxson[x],sz[to[i]]);
}
mxson[x]=max(mxson[x],nowsz-sz[x]);
if(!rt||mxson[x]<mxson[rt]) rt=x;
}
struct node{
int x,len;
node(){}
node(int x,int len):x(x),len(len){}
friend bool operator <(const node &A,const node&B) {
return A.len>B.len||(A.len==B.len&&A.x<B.x);
}
}tpn,tpt;
struct Node{
int fi,se;
Node(){}
Node(int fi,int se):fi(fi),se(se){}
friend bool operator <(const Node &A,const Node&B) {
return A.fi+A.se>B.fi+B.se;
}
}tpN;
set<node>s[N];
multiset<int>t[N];
multiset<Node>mx;
#define IT set<node>::iterator
#define It multiset<Node>::iterator
int ec,F[N],nx[N],tt[N];
void ADD(int u,int v) {
nx[++ec]=F[u]; F[u]=ec; tt[ec]=v;
}
void calc(int x,int f) {
int fi=-1,se=-1;
for(int i=F[x];i;i=nx[i]) if(nf[tt[i]]==x) {
if(!t[tt[i]].empty()) {
int tlen=*t[tt[i]].rbegin();
se=max(se,tlen);
if(se>fi) swap(fi,se);
}
}
if(!clo[x]) se=max(se,0); if(se>fi) swap(se,fi);
if(!f&&g[x][0]!=-1&&g[x][1]!=-1)
mx.erase(mx.find(Node(g[x][0],g[x][1])));
g[x][0]=fi; g[x][1]=se;
if(fi!=-1&&se!=-1) mx.insert(Node(fi,se));
}
void get_devide(int x,int fa) {
if(fa) ADD(fa,x);
nf[x]=fa;
vis[x]=1;
for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]) {
rt=0; nowsz=sz[to[i]];
get_root(to[i],0); int tprt=rt;
get_devide(rt,x);
for(IT it=s[tprt].begin();it!=s[tprt].end();it++) {
tpn=*it;
int dis=get_lca(tpn.x,x);
t[tprt].insert(dis);
s[x].insert(node(tpn.x,dis));
}
}
s[x].insert(node(x,0));
calc(x,1);
}
void open(int y,int x,int len) {
s[y].insert(node(x,len));
if(nf[y]) t[y].insert(get_lca(x,nf[y]));
if(len>g[y][0]||len>g[y][1]) calc(y,0);
if(nf[y]) open(nf[y],x,get_lca(nf[y],x));
}
void close(int y,int x,int len) {
s[y].erase(node(x,len));
if(nf[y]) t[y].erase(t[y].find(get_lca(x,nf[y])));
if(len==g[y][0]||len==g[y][1]) calc(y,0);
if(nf[y]) close(nf[y],x,get_lca(nf[y],x));
}
int totclose;
int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
memset(g,-1,sizeof(-1));
read(n); nowsz=n;
for(int i=1;i<n;i++) {
int u,v;
read(u); read(v);
add(u,v);
}
dfs1(1,0);
get_root(1,0);
get_devide(rt,0);
read(Q); totclose=n;
while(Q--) {
scanf("%s",o);
if(o[0]==‘C‘) {
int x;
read(x);
if(clo[x]==1) {
clo[x]=0;
open(x,x,0);
totclose++;
}
else {
clo[x]=1;
close(x,x,0);
totclose--;
}
}
else {
if(totclose==1) puts("0");
else if(totclose==0) puts("-1");
else {
Node tp=*mx.begin();
int ans=tp.fi+tp.se;
printf("%d\n",ans);
}
}
}
return 0;
}
/*
5
1 2
2 3
1 4
2 5
10
C 5
C 3
C 2
G
*/