传送门
题意
给你 个节点的树。 个操作
- 1 v 把v和儿子全部置为1
- 2 v 把root到v之间全部置为0
- 3 v 查询v
思路
树上的区间操作,很明显的一个树链刨分+线段树维护
线段树的flag数组表示置为0或者1.
区间修改+单点查询
代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 5e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
int id[man],rk[man],top[man],siz[man];
int son[man],dep[man],fa[man];
vector<int>sp[man];
void dfs1(int u,int f,int d){
son[u] = 0;
dep[u] = d;
fa[u] = f;
siz[u] = 1;
for(int i = 0;i < sp[u].size();i++){
int v = sp[u][i];
if(v==f)continue;
dfs1(v,u,d+1);
siz[u] += siz[v];
if(siz[son[u]]<siz[v]){
son[u] = v;
}
}
}
int cnt = 0;
void dfs2(int u,int tp){
id[u] = ++cnt;
rk[cnt] = u;
top[u] = tp;
if(!son[u])return;
dfs2(son[u],tp);
for(int i = 0;i < sp[u].size();i++){
int v = sp[u][i];
if(v==son[u]||v==fa[u])continue;
dfs2(v,v);
}
}
int flag[man<<2],tr[man<<2],a[man];
void pushdown(int rt){
if(flag[rt]){
flag[rt<<1] = flag[rt];
flag[rt<<1|1] = flag[rt];
tr[rt<<1] = (flag[rt]==1 ? 1 : 0);
tr[rt<<1|1] = (flag[rt]==1 ? 1 : 0);
flag[rt] = 0;
}
}
void update(int l,int r,int L,int R,int rt,int op){
if(L<=l&&r<=R){
flag[rt] = op;//1 full 2 empty
tr[rt] = (op==1 ? 1 : 0);
return;
}
int m = l + r >> 1;
pushdown(rt);
if(L<=m)update(l,m,L,R,rt<<1,op);
if(R>m)update(m+1,r,L,R,rt<<1|1,op);
}
int query(int l,int r,int rt,int v){
if(l==r){
return tr[rt];
}
int m = l + r >> 1;
pushdown(rt);
if(v<=m)return query(l,m,rt<<1,v);
else return query(m+1,r,rt<<1|1,v);
}
void tree_update(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
update(1,cnt,id[top[x]],id[x],1,2);
x = fa[top[x]];
//cout << x << " "<< top[x] << " "<< y << endl;
}
if(dep[x]<dep[y]){
swap(x,y);
}
update(1,cnt,id[y],id[x],1,2);
//cout << x << " "<< y << endl;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n;
scanf("%d",&n);
for(int i = 1;i < n;i++){
int u,v;
scanf("%d%d",&u,&v);
sp[u].push_back(v);
sp[v].push_back(u);
}
int m;
dfs1(1,1,1);
dfs2(1,1);
// for(int i = 1;i <= n;i++){
// cout << id[i] << " " <<rk[id[i]] << endl;
// }
scanf("%d",&m);
for(int i = 1;i <= m;i++){
int op;
scanf("%d",&op);
//cout << "op" << op << endl;
if(1==op){
int v;scanf("%d",&v);
update(1,cnt,id[v],id[v]+siz[v]-1,1,1);
}else if(2==op){
int v;scanf("%d",&v);
tree_update(1,v);
}else{
int v;scanf("%d",&v);
// cout << "v:" << v << endl;
printf("%d\n",query(1,cnt,1,id[v]));
}
}
return 0;
}