题目背景

在一个叫做Travian的世界里,生活着各个大大小小的部落。其中最为强大的是罗马、高卢和日耳曼。他们之间为了争夺资源和土地,进行了无数次的战斗。期间诞生了众多家喻户晓的英雄人物,也留下了许多可歌可泣的动人故事。

其中,在大大小小的部落之间,会有一些道路相连,这些道路是Travian世界里的重要枢纽,简单起见,你可以把这些部落与部落之间相连的道路看作一颗树,可见每条道路对于Travian世界的重要程度。有了这些道路,建筑工人就可以通过这些道路进行友好外交啦。

然而,事情并不会像想象的那样美好,由于资源的匮乏,相邻的部落(由一条道路相连的部落)之间经常会发生大大小小的冲突事件,更有甚者,会升级为部落之间的大型战争。

为了避免误伤,每当两个相邻的部落之间发生大型战争之时,这两个部落间的道路是不允许通行的,对于一些强大的部落,甚至能与多个相邻的部落同时开战,同样的,这些战争地带的道路十分危险,是不可通行的。

天下之势,分久必合,当两个部落经历了不打不相识的苦战之后,他们可以签订停战协议(暂时停战,以后依旧可能再次开战),这样,两个部落之间的道路又会重新恢复为可通行状态,建筑工人们又可以经过此地购买最新的大本营设计图纸来强大自己的部落了。

为了简单起见,我们把各大战争事件按发起的时间顺序依次编号(最先发起的战争编号就为 1,第二次战争编号就为 2,以此类推),当两个部落停战之时,则会直接告诉你这场战争的编号,然后这场战争就载入了史册,不复存在了,当然,这并不会影响到其他战争的编号。

建筑工人十分讨厌战争,因为战争,想从一个部落到另一个部落进行友好交流的建筑工人可能就此白跑一趟。所以,在他们出发之前,都会向你问问能不能到达他们想去的部落。

题目描述

简单起见,你就是要处理下面三件事,所有的事件都是按照时间顺序给出的。

1.(部落冲突架构 部落冲突简述_输入输出 部落冲突架构 部落冲突简述_#include_02 部落冲突架构 部落冲突简述_输入输出_03 )从第 部落冲突架构 部落冲突简述_#include_02 个部落出发的建筑工人想知道能否到达第 部落冲突架构 部落冲突简述_输入输出_03 个部落了,你要回答的便是(Yes/No),注意大小写

2.(部落冲突架构 部落冲突简述_#include_06 部落冲突架构 部落冲突简述_#include_02 部落冲突架构 部落冲突简述_输入输出_03 )第 部落冲突架构 部落冲突简述_#include_02 个部落与第 部落冲突架构 部落冲突简述_输入输出_03 个部落开战了,保证他们一定是相邻的部落,且目前处于停战(未开战)状态

3.(部落冲突架构 部落冲突简述_部落冲突架构_11 部落冲突架构 部落冲突简述_部落冲突架构_12 ) 第 部落冲突架构 部落冲突简述_部落冲突架构_12 次发生的战争结束了,它将永远的被载入史册,不复存在(保证这个消息不会告诉你多次)

输入输出格式


输入格式:

第一行两个数 部落冲突架构 部落冲突简述_数据_14 和 部落冲突架构 部落冲突简述_输入输出_15 , 部落冲突架构 部落冲突简述_数据_14 代表了一共有 部落冲突架构 部落冲突简述_数据_14 个部落,部落冲突架构 部落冲突简述_输入输出_15 代表了以上三种事件发生的总数

接下来的 部落冲突架构 部落冲突简述_数据_19 行,每行两个数 部落冲突架构 部落冲突简述_#include_02 , 部落冲突架构 部落冲突简述_输入输出_03 ,代表了第 部落冲突架构 部落冲突简述_#include_02 个部落与第 部落冲突架构 部落冲突简述_输入输出_03 个部落之间有一条道路相连

接下来的 部落冲突架构 部落冲突简述_输入输出_15 行,每行表示一件事,详见题目描述


输出格式:

每行一个“部落冲突架构 部落冲突简述_数据_25 ”或者“部落冲突架构 部落冲突简述_输入输出_26 ”,表示从第 部落冲突架构 部落冲突简述_#include_02 个部落出发的建筑工人能否到达第 部落冲突架构 部落冲突简述_输入输出_03 个部落

输入输出样例


输入样例#1: 

5 9 1 2 2 3 3 4 4 5 Q 1 4 C 2 1 C 4 3 Q 3 1 Q 1 5 U 1 U 2 C 4 3 Q 3 4



输出样例#1: 

Yes No No No


























输入样例#2: 

10 10 1 2 1 3 3 4 3 5 1 6 3 7 1 8 2 9 5 10 C 8 1 Q 6 1 C 2 1 Q 2 10 U 1 C 9 2 C 7 3 U 3 Q 6 7 Q 1 10



输出样例#2: 

Yes No No Yes






































输入样例#3: 

20 20 1 2 1 3 2 4 1 5 1 6 4 7 1 8 2 9 5 10 1 11 2 12 7 13 1 14 1 15 11 16 4 17 3 18 18 19 8 20 Q 13 5 C 14 1 C 16 11 U 1 U 2 C 20 8 Q 7 1 C 7 4 Q 17 17 Q 1 6 C 16 11 C 2 1 Q 16 2 U 3 U 5 U 6 C 2 1 C 6 1 C 13 7 C 11 1



输出样例#3: 

Yes Yes Yes Yes No


说明

对于30%的数据 1<=n,m<=6000

对于另30%的数据,保证部落之间的地理关系是一条链,且 i 与 i + 1 之间有一条道路

对于另30%的数据,1<=n,m<=100000

对于100%的数据,1<=n,m<=300000

裸的LCT。。。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 300010
using namespace std;
int n,m,c=1;
int top,stack[MAXN];
struct LCT{
	int f,flag,son[2];
}a[MAXN];
struct node{
	int u,v;
}que[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline bool isroot(int rt){
	return a[a[rt].f].son[0]!=rt&&a[a[rt].f].son[1]!=rt;
}
inline void pushup(int rt){
	return;
}
inline void pushdown(int rt){
	if(!rt||!a[rt].flag)return;
	a[a[rt].son[0]].flag^=1;a[a[rt].son[1]].flag^=1;a[rt].flag^=1;
	swap(a[rt].son[0],a[rt].son[1]);
}
inline void turn(int rt){
	int x=a[rt].f,y=a[x].f,k=a[x].son[0]==rt?1:0;
	if(!isroot(x)){
		if(a[y].son[0]==x)a[y].son[0]=rt;
		else a[y].son[1]=rt;
	}
	a[rt].f=y;a[x].f=rt;a[a[rt].son[k]].f=x;
	a[x].son[k^1]=a[rt].son[k];a[rt].son[k]=x;
	pushup(x);pushup(rt);
}
void splay(int rt){
	top=0;
	stack[++top]=rt;
	for(int i=rt;!isroot(i);i=a[i].f)stack[++top]=a[i].f;
	while(top)pushdown(stack[top--]);
	while(!isroot(rt)){
		int x=a[rt].f,y=a[x].f;
		if(!isroot(x)){
			if((a[y].son[0]==x)^(a[x].son[0]==rt))turn(rt);
			else turn(x);
		}
		turn(rt);
	}
}
void access(int rt){
	for(int i=0;rt;i=rt,rt=a[rt].f){
		splay(rt);
		a[rt].son[1]=i;
		pushup(rt);
	}
}
inline void makeroot(int rt){access(rt);splay(rt);a[rt].flag^=1;}
int find(int rt){
	access(rt);splay(rt);
	while(a[rt].son[0])rt=a[rt].son[0];
	return rt;
}
inline void split(int x,int y){makeroot(x);access(y);splay(y);}
inline void link(int x,int y){makeroot(x);a[x].f=y;}
inline void cut(int x,int y){split(x,y);a[x].f=a[y].son[0]=0;}
void work(){
	int x,y;
	char ch[2];
	for(int cases=1;cases<=m;cases++){
		scanf("%s",ch);x=read();
		if(ch[0]=='Q'){
			y=read();
			if(find(x)==find(y))printf("Yes\n");
			else printf("No\n");
		}
		if(ch[0]=='C'){
			y=read();
			que[c].u=x;que[c].v=y;
			c++;
			cut(x,y);
		}
		if(ch[0]=='U')link(que[x].u,que[x].v);
	}
}
void init(){
	int x,y;
	n=read();m=read();
	for(int i=1;i<n;i++){
		x=read();y=read();
		link(x,y);
	}
}
int main(){
	init();
	work();
	return 0;
}