题目大意:
给出一个具有N个点的树,1号节点是根节点。现在有三种操作:
①1 x,表示给x节点灌溉水,并且其儿子都会被灌上水。
②2 x,表示将x节点的水抽干,并且其父亲节点会一路被抽干。
③3 x,表示询问x节点是否有水。有水输出1,否则输出0。
思路(思路参考自:http://blog.csdn.net/u014410316/article/details/51037532):
①很显然,我们如果一个点是有水的,那么其子树就都一定有水。
②同理,我们如果一个点是没水的,那么其父亲就一定没有水。
Dfs序大家还是都会的这里不啰嗦了。
那么我们对于查询(操作3)操作,我们只要查询这个点的子树是否都是1即可,如果都是1的话,那么输出1,否则就是0.
那么对于操作2,我们对应单点修改线段树置0即可。
那么对于操作1,如果我们当前点的子树不都有水,那么先置其父亲为0(这样再查询上边的祖先节点的时候才能保证结果正确,我们这个操作相当于将一个抽干的点上置一下,很容易理解).然后再将整个子树区间置1即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
vector<int>mp[600000];
int L[600000];
int R[600000];
int fa[600000];
int cnt;
void Dfs(int u,int from)
{
fa[u]=from;
L[u]=++cnt;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(v==from)continue;
Dfs(v,u);
}
R[u]=cnt;
}
/****************************/
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int tree[500500*4];
int flag[500050*4];
void pushup(int rt)
{
tree[rt]=(tree[rt*2]&&tree[rt*2+1]);
}
void pushdown(int l,int r,int rt)
{
if(flag[rt])
{
int m=(l+r)/2;
flag[rt*2]=flag[rt];
flag[rt*2+1]=flag[rt];
tree[rt*2]=flag[rt];
tree[rt*2+1]=flag[rt];
flag[rt]=0;
}
}
void build(int l,int r,int rt)
{
tree[rt]=flag[rt]=0;
if(l==r)return ;
int m=(l+r)/2;
build(lson);build(rson);pushup(rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(l>=L&&r<=R)
{
flag[rt]=tree[rt]=c;
return ;
}
pushdown(l,r,rt);
int m=(l+r)/2;
if(L<=m)update(L,R,c,lson);
if(R>m)update(L,R,c,rson);
pushup(rt);
}
void update_Del(int p,int l,int r,int rt)
{
if(l==r)
{
tree[rt]=0;
return ;
}
pushdown(l,r,rt);
int m=(l+r)/2;
if(p<=m)update_Del(p,lson);
if(p>m)update_Del(p,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(l>=L&&r<=R)
{
return tree[rt];
}
int ans=1;
pushdown(l,r,rt);
int m=(l+r)/2;
if(L<=m)ans=min(ans,query(L,R,lson));
if(R>m)ans=min(ans,query(L,R,rson));
pushup(rt);
return ans;
}
/****************************/
int main()
{
int n;
while(~scanf("%d",&n))
{
cnt=0;
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=1;i<=n-1;i++)
{
int x,y;scanf("%d%d",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
Dfs(1,-1);
build(1,n,1);
int q;scanf("%d",&q);
while(q--)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==1)
{
if(!query(L[x],R[x],1,n,1)&&fa[x]!=-1)update_Del(L[fa[x]],1,n,1);
update(L[x],R[x],1,1,n,1);
}
if(op==2)
{
update_Del(L[x],1,n,1);
}
if(op==3)
{
printf("%d\n",query(L[x],R[x],1,n,1));
}
}
}
}