標籤:個數 printf script algorithm cst reg out des ++
Description
在2016年,佳媛姐姐剛剛學習了樹,非常開心。現在他想解決這樣一個問題:給定一顆有根樹(根為1),有以下兩種操作:
- 標記操作:對某個結點打上標記(在最開始,只有結點1有標記,其他結點均無標記,而且對於某個結點,可以打多次標記。)
- 詢問操作:詢問某個結點最近的一個打了標記的祖先(這個結點本身也算自己的祖先)
你能幫幫他嗎?
Input
輸入第一行兩個正整數N和Q分別表示節點個數和操作次數
接下來N-1行,每行兩個正整數u,v(1≤u,v≤n)表示u到v有一條有向邊
接下來Q行,形如“opernum”oper為“C”時表示這是一個標記操作,oper為“Q”時表示這是一個詢問操作對於每次詢問操作。
Output
輸出一個正整數,表示結果。
令人窒息的一個題,洛穀上暴力\(A\)了?
但是bzoj上T的飛起 emm
聽學長說,這題是樹剖。
但是暴力\(A\)掉了。於是寫正解就向後拖一拖 emmm
小最佳化:如果沒有修改操作,直接輸出\(1\)。
代碼
#include<cstdio>#include<iostream>#include<algorithm>#define R registerusing namespace std;const int gz=100008;inline void in(int &x){ int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f;}int n,q;int f[gz],tg[gz];char opt[5];inline int work(R int x){ if(tg[x])return x; while(f[x]) { x=f[x]; if(tg[x])return x; }}bool flg;int main(){ in(n),in(q); for(R int i=1,x,y;i<n;i++) in(x),in(y),f[y]=x; tg[1]=true; for(R int i=1,x;i<=q;i++) { scanf("%s",opt+1); if(opt[1]=='Q') { in(x); if(!flg)puts("1"); else printf("%d\n",work(x)); } else { in(x),flg=true; tg[x]=true; } }}
暴力 【p4092】[HEOI2016/TJOI2016]樹