Description
做爲一名高級特工,Idiot 苦心經營多年,終於在敵國創建起一張共有n 名特工的龐大間諜網絡。
固然,出於保密性的要求,間諜網絡中的每名特工最多隻會有一名直接領導。如今,Idiot 但願整理有關歷次特別行動的一些信息。
初始時,間諜網絡中的全部特工都沒有直接領導。以後,共有m 次下列類型的事件按時間順序依次發生:
• 事件類型1 x y:特工y 成爲特工x 的直接領導。數據保證在此以前特工x 沒有直接領導;
• 事件類型2 x:特工x 策劃了一塊兒特別行動,而後上報其直接領導審批,以後其直接領導再上報其直接領導的直接領導審批,以此類推,直到某個特工審批後再也不有直接領導;
• 事件類型3 x y:詢問特工x 是否直接策劃或審批過第y 次特別行動。全部特別行動按發生時間的順序從1 開始依次編號。數據保證在詢問以前,第y 次特別行動已經發生過。
做爲一名高級特工,Idiot 固然不會親自辦事。因而,Idiot 便安排你來完成這個任務。算法
Input
第一行兩個正整數n 和m,分別表示間諜網絡中的特工總數,以及事件的總數。
接下來m 行,第i 行給出第i 個事件的信息,格式及含義參見題面。網絡
Output
輸出共t 行,其中t 表示詢問的總數。第i 行輸出」Y ES」 或者」NO」,表示第i 次詢問的答案。spa
Sample Input
6 12 2 1 1 4 1 3 4 1 1 3 4 2 3 3 4 1 2 3 3 4 2 3 1 1 3 1 3 3 1 2 1 2 4
Sample Output
NO NO YES YES YES YES
Data Constraint
對於30% 的數據,n <= 3 *10^3,m <= 5* 10^3; 對於60% 的數據,n <=2 * 10^5,m <= 2 * 10^5; 額外20% 的數據,保證在任意時刻,整張間諜網絡由若干條互不相交的鏈構成; 對於100% 的數據,n <= 5 * 10^5,m <= 5 * 10^5; C + + 選手的程序在評測時使用編譯選項-Wl;--stack = 104857600。
code
這一題主要是要求\(x\)在某時刻是不是\(y\)的祖先,搞得好像是強制在線,但實際上仍是離線算法您敢信?blog
樣例的最後圖變成了:事件
先考慮第一個問題,\(x\)是不是\(y\)的祖先。ip
很顯然,有一種方法是判斷\(lca(x,y)=x\),但實際還有更簡單的方法就是\(dfs\)序。get
預處理出某節點在\(dfs\)序加入和退出的時間戳,就能夠\(O(1)\)運用了。input
還有個問題,咱們要求的是在某個時刻,那咱們怎麼知道在那個時刻\(x\)是否是\(y\)的祖先?以前說了,這是離線的算法,因此咱們能夠先讀入一遍,保存數據進行操做後,再讀一遍,遇到操做\(1\)就用個並查集表示在某時刻\(x\)和\(y\)纔有關係。io
sort(a + 1, a + 1 + cnt, cmp); for (int i = 1; i <= n; i++) if(!flag[i]) dfs(i); //dfs序 tot = 0; int j = 1; for (int i = 1; i <= m; i++) { if(opt[i] == 1)fa[getfa(x[i])] = getfa(y[i]); //冰茶几 if(opt[i] == 2) { ++tot; while(a[j].y == tot && j <= cnt) { if (getfa(a[j].x) == getfa(x[i]) && beg[a[j].x] <= beg[x[i]] && beg[x[i]] <= en[a[j].x]) ans[a[j].total] = 1; j++; } } }