传送门
题意:
给你一棵树,有三种操作:
1. 给一个点及其子孙赋值为1
2. 给一个点及其祖先赋值为0
3. 求一个点是1还是0
Solution:
这道题显然可以用树剖做,但是复杂度不优秀(两个log),这里说一种一个log的做法:
先跑出树的dfs序,对dfs序建一棵线段树,那么操作1就变的非常简单,我们重点需要考虑的是操作2:暴力给每个点赋值是会T的,我们可以先只修改一个最下面的点,即这个点本身,那么就需要把3操作改为查询这个点的子树是否全1,因为如果这个点的子树中不是全1,那么这个点一定是0,只是这个点并没有被更新到而已,同时,在操作1中,如果我们选中的这个点为0,那么我们就需要把0往上更新,因为这个点及其子树将会再次被全赋成1,如果不往上更新的话0的信息就会被覆盖从而导致体现不出来了。
代码:
#include<cstdio>
#include<iostream>
using namespace std;
const int N=500010;
struct edg{
int to,next;
}e[2*N];
int n,m;
int fa[N];
int size,head[N];
bool vis[N];
struct tree{
int l,r;
bool v,tag;
}tr[4*N];
int x,y,tot;
int bg[N],ed[N];
void add(int x,int y)
{
size++;
e[size].to=y;
e[size].next=head[x];
head[x]=size;
}
void dfs(int x,int f)
{
bg[x]=++tot;
fa[x]=f;
for (int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if (y!=f) dfs(y,x);
}
ed[x]=tot;
}
void update(int i)
{
tr[i].v=tr[i<<1].v*tr[i<<1|1].v;
}
void build(int i,int l,int r)
{
tr[i].l=l;tr[i].r=r;
if (l==r) return;
int mid=l+r>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}
void addtag(int x,int val)
{
tr[x].tag=val;
tr[x].v=val;
}
void pushdown(int i)
{
if (tr[i].tag)
{
tr[i].tag=0;
if (tr[i].l==tr[i].r) return;
addtag(i<<1,1);
addtag(i<<1|1,1);
}
}
void modify(int i,int l,int r)
{
int L=tr[i].l,R=tr[i].r;
if (l>R||L>r) return;
pushdown(i);
if (l<=L&&R<=r){addtag(i,1);return;}
modify(i<<1,l,r);
modify(i<<1|1,l,r);
update(i);
}
void md0(int i,int pos)
{
int L=tr[i].l,R=tr[i].r;
pushdown(i);
if (L==R) {
tr[i].v=0;return;}
int mid=L+R>>1;
if (pos<=mid) md0(i<<1,pos);
else md0(i<<1|1,pos);
update(i);
}
bool query(int i,int l,int r)
{
int L=tr[i].l,R=tr[i].r;
if (l>R||L>r) return 1;
pushdown(i);
if (l<=L&&R<=r){
return tr[i].v;}
return query(i<<1,l,r)*query(i<<1|1,l,r);
}
int main()
{
//freopen("343D.in","r",stdin);
//freopen("343D.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<n;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(1,0);
build(1,1,tot);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if (x==1) {
if (y!=1&&!query(1,bg[y],ed[y]))md0(1,bg[fa[y]]);modify(1,bg[y],ed[y]);}
else if (x==2) md0(1,bg[y]);
else if (x==3) printf("%d\n",query(1,bg[y],ed[y]));
}
}