暂无链接
零食
题目背景
最终还是放弃了买牛奶,选择了买零食。
题目描述
由于是一只有收集癖的猫,他会把很多零食堆在他的窝里面。
的窝由个独立的房间组成,房间与房间之间有条过道,且从任意一个独立的房间可以经过过道到达其他所有的房间,的窝的入口在号房间处。
由于买了太多的零食,所以他每次会选择一个房间,携带巨量零食,从猫窝的入口走到这个房间。他会在走过的房间里做上记号,方便等会儿原路返回。(目标房间不会被做上记号)
到达这个目标房间后,会从这个房间开始,把所有 可以不经过做了记号房间就可以达到的房间 中堆满零食。做完后,他会沿着他放下的记号离开猫窝,并且把这些记号抹去。
听说买了很多零食,再加上他今天很饿,于是他决定去偷吃一部分。
每次会选择一个房间,从号房间进入的窝,然后直接走向那个房间。他会把路上经过的所有房间中的所有零食全部吃掉。
由于有很多集,这样的事情也不可能只发生了一次。
在多次买来零食后,发现自己的零食仿佛被人吃掉了不少,于是他心生好奇:在我的窝里的某个房间里,现在还有没有零食啊?
请编写一个程序帮解决这个问题。
一句话题意:
给定一颗个点,号节点为根的树,支持三种操作:
给定子树中所有点的权值赋值为,从根到某个节点的路径上所有点的权值赋值为,查询一个点的权值。
输入格式
第一行输入一个整数,代表的窝有个房间。
接下来行,每行输入两个数字,代表的窝中,编号为的房间与编号为的房间之间有一条过道。
下一行输入一个整数,代表接下来有次 有关零食的事件或的好奇。
接下来行,每行两个数
若,则表示按照上述规则走到了号房间,并堆了一波零食。
若,则表示光顾了的窝,从号房间走到号房间,顺便吃掉了路上房间的零食。
若,则表示现在很好奇,号房间中还有没有零食。
输出格式
对于每一个,你需要输出一行一个数字。
若房间中有零食,则输出,否则输出。
输入样例
5
1 2
5 1
2 3
4 2
12
1 1
2 3
3 1
3 2
3 3
3 4
1 2
2 4
3 1
3 3
3 4
3 5
输出样例
0
0
0
1
0
1
0
1
数据范围
对于的数据,保证
对于的数据,保证
对于的数据,保证
出题人会尽力卡掉的同学
题解
子树操作的话用线段树+序就可以了,点到根的路径的话有点奇妙,因为点到根的路径与子树是互逆的关系,我们把赋值为的标记打到链的最底端,子树赋值为时查询自己子树内有没有,如果有的话就把标记扔到自己父亲那儿,然后区间赋值即可,查询同理。
代码
#include<bits/stdc++.h>
#define add(a,b) nxt[++cnt]=head[a],head[a]=cnt,to[cnt]=b
#define ls v<<1
#define rs ls|1
using namespace std;
const int M=5e5+5;
int head[M],nxt[M<<1],to[M<<1],dfn[M],dad[M],ri[M],n,m,cnt,df;
bool all[M<<2],tag[M<<2];
void dfs(int v,int f){dfn[v]=++df,dad[v]=f;for(int i=head[v];i;i=nxt[i])if(to[i]!=f)dfs(to[i],v);ri[v]=df;}
void up(int v){all[v]=all[ls]&all[rs];}
void push(int v){if(tag[v])all[ls]=tag[ls]=all[rs]=tag[rs]=1;tag[v]=0;}
bool ask(int v,int l,int r,int lb,int rb)
{
if(lb<=l&&r<=rb)return all[v];
int mid=l+r>>1,ans=1;push(v);
if(lb<=mid)ans=ask(ls,l,mid,lb,rb);
if(mid<rb)ans&=ask(rs,mid+1,r,lb,rb);
up(v);return ans;
}
void modi(int v,int l,int r,int lb,int rb)
{
if(lb<=l&&r<=rb){tag[v]=all[v]=1;return;}
int mid=l+r>>1;
if(lb<=mid)modi(ls,l,mid,lb,rb);
if(mid<rb)modi(rs,mid+1,r,lb,rb);
}
void modi(int v,int l,int r,int pos)
{
if(l==r){all[v]=0;return;}
int mid=l+r>>1;push(v);
if(pos<=mid)modi(ls,l,mid,pos);
else modi(rs,mid+1,r,pos);
up(v);
}
void in(){scanf("%d",&n);for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),add(a,b),add(b,a);}
void ac()
{
dfs(1,0);scanf("%d",&m);
for(int op,a;m--;)
{
scanf("%d%d",&op,&a);
if(op==1){if(!ask(1,1,n,dfn[a],ri[a]))modi(1,1,n,dfn[dad[a]]);modi(1,1,n,dfn[a],ri[a]);}
else if(op==2)modi(1,1,n,dfn[a]);
else printf("%d\n",ask(1,1,n,dfn[a],ri[a]));
}
}
int main(){in(),ac();}