题目链接
冒着滥用此题将封号的风险测了七发RP才过……
每个点建两个双堆,堆a表示这个点所在的子树里所有点到他点分树中父亲的距离,堆b表示所有点分树子树中到他距离最大的个点的距离,堆c用来存全局答案,显然全局答案就是每个堆b中最大值和次大值的和
点分树上暴跳父亲复杂度是log的,所以总复杂度是 n l o g 2 n nlog^2n nlog2n
代码如下:
#include
using namespace std;
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
struct heap
{
priority_queue<int> q1,q2;
void insert(int val)
{
q1.push(val);
}
void erase(int val)
{
q2.push(val);
}
int top()
{
while(q2.size()&&q1.top()==q2.top()) q1.pop(),q2.pop();
return q1.top();
}
void pop()
{
while(q2.size()&&q1.top()==q2.top()) q1.pop(),q2.pop();
if(q1.size()) q1.pop();
}
int top2()
{
int val=top();pop();
int res=top();insert(val);
return res;
}
int size()
{
return q1.size()-q2.size();
}
}a[100010],b[100010],c;
int sz[100010],deep[100010];
int fa[100010],f[100010],fu[100010][18];
bool vis[100010],s[100010];
int n,m;
vector<int> g[100010];
void dfs(int now,int ff)
{
deep[now]=deep[ff]+1;
fu[now][0]=ff;
for(int i=1;i<=17;i++)
{
fu[now][i]=fu[fu[now][i-1]][i-1];
}
for(int i=0;i<g[now].size();i++)
{
if(g[now][i]==ff) continue;
dfs(g[now][i],now);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
for(int i=17;i>=0;i--)
{
if(deep[fu[x][i]]>=deep[y])
{
x=fu[x][i];
}
}
if(x==y) return x;
for(int i=17;i>=0;i--)
{
if(fu[x][i]!=fu[y][i])
{
x=fu[x][i];
y=fu[y][i];
}
}
return fu[x][0];
}
inline int dis(int x,int y)
{
int anc=lca(x,y);
return deep[x]+deep[y]-2*deep[anc];
}
void get_sz(int now,int ff)
{
sz[now]=1;
f[now]=ff;
for(int i=0;i<g[now].size();i++)
{
if(vis[g[now][i]]||g[now][i]==ff) continue;
get_sz(g[now][i],now);
sz[now]+=sz[g[now][i]];
}
}
int get_zx(int now,int ff)
{
if(sz[now]==1) return now;
int son,maxson=-1;
for(int i=0;i<g[now].size();i++)
{
if(vis[g[now][i]]||g[now][i]==ff) continue;
if(sz[g[now][i]]>maxson)
{
son=g[now][i];
maxson=sz[g[now][i]];
}
}
int zzx=get_zx(son,now);
while(sz[zzx]<sz[now]-sz[zzx]) zzx=f[zzx];
return zzx;
}
void dfs2(int now,int ff,int rtt,int zx)
{
a[zx].insert(dis(rtt,now));
for(int i=0;i<g[now].size();i++)
{
if(vis[g[now][i]]||g[now][i]==ff) continue;
dfs2(g[now][i],now,rtt,zx);
}
}
void build(int now,int ff)
{
b[now].insert(0);
fa[now]=ff;
vis[now]=1;
for(int i=0;i<g[now].size();i++)
{
if(g[now][i]==ff||vis[g[now][i]]) continue;
get_sz(g[now][i],0);
int zx=get_zx(g[now][i],0);
dfs2(zx,0,now,zx);
build(zx,now);
int dd=dis(zx,now);
b[now].insert(a[zx].top());
}
if(b[now].size()>1) c.insert(b[now].top()+b[now].top2());
}
void turn_on(int pos)
{
int pre,rtt=pos;
if(b[pos].size()>1) c.erase(b[pos].top()+b[pos].top2());
b[pos].insert(0);
if(b[pos].size()>1) c.insert(b[pos].top()+b[pos].top2());
while(fa[pos])
{
pre=pos;
pos=fa[pos];
if(b[pos].size()>1) c.erase(b[pos].top()+b[pos].top2());
if(a[pre].size()>0) b[pos].erase(a[pre].top());
a[pre].insert(dis(rtt,pos));
b[pos].insert(a[pre].top());
if(b[pos].size()>1) c.insert(b[pos].top()+b[pos].top2());
}
}
void turn_off(int pos)
{
int pre,rtt=pos;
if(b[pos].size()>1) c.erase(b[pos].top()+b[pos].top2());
b[pos].erase(0);
if(b[pos].size()>1) c.insert(b[pos].top()+b[pos].top2());
while(fa[pos])
{
pre=pos;
pos=fa[pos];
if(b[pos].size()>1) c.erase(b[pos].top()+b[pos].top2());
b[pos].erase(a[pre].top());
a[pre].erase(dis(rtt,pos));
if(a[pre].size()>0) b[pos].insert(a[pre].top());
if(b[pos].size()>1) c.insert(b[pos].top()+b[pos].top2());
}
}
int main()
{
int from,to;
n=read();
for(int i=1;i<n;i++)
{
from=read();
to=read();
g[from].push_back(to);
g[to].push_back(from);
}
dfs(1,0);
build(1,0);
scanf("%d",&m);
char opt[2];
while(m--)
{
scanf("%s",opt);
if(opt[0]=='G')
{
printf("%d\n",c.top());
}
else
{
to=read();
s[to]^=1;
if(s[to]) turn_off(to);
else turn_on(to);
}
}
}