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++; } } }