传送门
解析:
其实说白了就是改变颜色,查询同色联通块大小。
有一个显然的做法就是维护两棵LCT,在改变颜色的时候该连的连,该断的断。
嗯,很显然会被菊花图卡掉。
考虑将所有点在同色的LCT中与父亲相连。同时 1 1 1的父亲设置为虚点 n + 1 n+1 n+1。
放弃makeroot操作,我们发现 l i n k link link和 c u t cut cut总是有明确的父子关系,魔改了。
上套路,维护虚子树大小。
对于询问,显然当前点所在的联通块的根节点与当前点是不同色的,access一下后取将根旋到Splay的根,询问右儿子的大小就行了。
显然access后根连着的链上向下就是和当前点所在的联通块。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
cs int N=1e5+5;
int last[N],nxt[N<<1],to[N<<1],ecnt;
inline void addedge(int u,int v){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v;
nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u;
}
struct LCT{
int fa[N],son[N][2],siz[N],val[N];
LCT(){for(int re i=1;i<N;++i)siz[i]=1;}
void pushup(int u){siz[u]=siz[son[u][0]]+siz[son[u][1]]+val[u]+1;}
bool which(int u){return son[fa[u]][1]==u;}
bool isroot(int u){return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;}
void Rotate(int u){
int Fa=fa[u],FA=fa[Fa];
bool pos=which(u);
if(!isroot(Fa))son[FA][which(Fa)]=u;
son[Fa][pos]=son[u][!pos];
if(son[u][!pos])fa[son[Fa][pos]]=Fa;
son[u][!pos]=Fa;
fa[Fa]=u,fa[u]=FA;
pushup(Fa);
pushup(u);
}
void Splay(int u){
for(int re Fa=fa[u];!isroot(u);Rotate(u),Fa=fa[u])
if(!isroot(Fa))Rotate(which(Fa)==which(u)?Fa:u);
}
void access(int u){
for(int re ch=0;u;u=fa[ch=u]){
Splay(u);
val[u]+=siz[son[u][1]];
val[u]-=siz[son[u][1]=ch];
pushup(u);
}
}
void link(int u,int v){
Splay(u);
fa[u]=v;
access(v);Splay(v);
val[v]+=siz[u],siz[v]+=siz[u];
}
void cut(int u,int v){
access(u);
Splay(u);
son[u][0]=fa[son[u][0]]=0;
pushup(u);
}
int query(int u){
access(u);
Splay(u);
while(son[u][0])u=son[u][0];
Splay(u);
return siz[son[u][1]];
}
}t[2];
int fa[N];
void dfs(int u){
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]])
if(v^fa[u])fa[v]=u,dfs(v),t[0].link(v,u);
}
bool col[N];
int n,q;
signed main(){
n=getint();
for(int re i=1;i<n;++i)addedge(getint(),getint());
dfs(1);
fa[1]=n+1;
t[0].link(1,fa[1]);
q=getint();
while(q--)switch(getint()){
case 1:{
int u=getint();
bool &c=col[u];
t[c].cut(u,fa[u]);
t[c^=1].link(u,fa[u]);
break;
}
case 0:{
int u=getint();
bool c=col[u];
std::cout<<t[c].query(u)<<"\n";
break;
}
}
return 0;
}