传送门
将一棵子树覆盖为1,将一点到根路径上的点覆盖为0,询问一个点是1还是0;
用树链剖分+线段树维护即可。
#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=5e5+5;
//il int Add(ll &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
vector<int> G[N];
int n,q,dep[N],sz[N],son[N],fa[N],id[N],bel[N],cnt;
il void dfs1(int x,int ff){
fa[x]=ff,dep[x]=dep[ff]+1,sz[x]=1;
int mx=-1;
for(auto to:G[x]){
if(to==ff) continue;
dfs1(to,x);
sz[x]+=sz[to];
if(sz[to]>mx) son[x]=to,mx=sz[to];
}
}
il void dfs2(int x,int topx){
id[x]=++cnt,bel[x]=topx;
if(!son[x])return;
dfs2(son[x],topx);
for(auto to:G[x]){
if(to==fa[x] || to==son[x]) continue;
dfs2(to,to);
}
}
int lz[N<<2],s[N<<2];
il void pushdown(int rt){
if(lz[rt]!=-1){
lz[rt<<1]=lz[rt],lz[rt<<1|1]=lz[rt];
s[rt<<1]=lz[rt],s[rt<<1|1]=lz[rt];
lz[rt]=-1;
}
}
il void update(int l,int r,int L,int R,int rt,int type){
if(L<=l && R>=r){
lz[rt]=type;
s[rt]=type;
return;
}
pushdown(rt);
if(L<=mid) update(l,mid,L,R,rt<<1,type);
if(R>mid) update(mid+1,r,L,R,rt<<1|1,type);
}
il bool query(int l,int r,int X,int rt){
if(l==r) return s[rt];
pushdown(rt);
if(X<=mid) return query(l,mid,X,rt<<1);
else return query(mid+1,r,X,rt<<1|1);
}
il void r_update(int x,int y){
while(bel[x]!=bel[y]){
if(dep[bel[x]]<dep[bel[y]]) swap(x,y);
update(1,n,id[bel[x]],id[x],1,0);
x=fa[bel[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(1,n,id[x],id[y],1,0);
}
il void p_update(int x){
update(1,n,id[x],id[x]+sz[x]-1,1,1);
}
int main(){
std::ios::sync_with_stdio(0);cin.tie(0);
ms(lz,-1);
cin>>n;
int x,y;
for(int i=1;i<=n-1;++i){
cin>>x>>y;
G[x].pb(y),G[y].pb(x);
}
dfs1(1,0),dfs2(1,1);
cin>>q;
for(int i=1;i<=q;++i){
cin>>x>>y;
if(x==1) p_update(y);
else if(x==2) r_update(1,y);
else cout<<query(1,n,id[y],1)<<endl;
}
return 0;
}