暫無鏈接
零食
題目背景
最終還是放棄了買牛奶,選擇了買零食。
題目描述
由於是一隻有收集癖的貓,他會把很多零食堆在他的窩裏面。
的窩由個獨立的房間組成,房間與房間之間有條過道,且從任意一個獨立的房間可以經過過道到達其他所有的房間,的窩的入口在號房間處。
由於買了太多的零食,所以他每次會選擇一個房間,攜帶巨量零食,從貓窩的入口走到這個房間。他會在走過的房間裏做上記號,方便等會兒原路返回。(目標房間不會被做上記號)
到達這個目標房間後,會從這個房間開始,把所有 可以不經過做了記號房間就可以達到的房間 中堆滿零食。做完後,他會沿着他放下的記號離開貓窩,並且把這些記號抹去。
聽說買了很多零食,再加上他今天很餓,於是他決定去偷吃一部分。
每次會選擇一個房間,從號房間進入的窩,然後直接走向那個房間。他會把路上經過的所有房間中的所有零食全部吃掉。
由於有很多集,這樣的事情也不可能只發生了一次。
在多次買來零食後,發現自己的零食彷彿被人吃掉了不少,於是他心生好奇:在我的窩裏的某個房間裏,現在還有沒有零食啊?
請編寫一個程序幫解決這個問題。
一句話題意:
給定一顆個點,號節點爲根的樹,支持三種操作:
給定子樹中所有點的權值賦值爲,從根到某個節點的路徑上所有點的權值賦值爲,查詢一個點的權值。
輸入格式
第一行輸入一個整數,代表的窩有個房間。
接下來行,每行輸入兩個數字,代表的窩中,編號爲的房間與編號爲的房間之間有一條過道。
下一行輸入一個整數,代表接下來有次 有關零食的事件或的好奇。
接下來行,每行兩個數
若,則表示按照上述規則走到了號房間,並堆了一波零食。
若,則表示光顧了的窩,從號房間走到號房間,順便吃掉了路上房間的零食。
若,則表示現在很好奇,號房間中還有沒有零食。
輸出格式
對於每一個,你需要輸出一行一個數字。
若房間中有零食,則輸出,否則輸出。
輸入樣例
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();}