1 /*
2 唐代白居易
3 《白云泉》
4 天平山上白云泉,云自无心水自闲。
5 何必奔冲山下去,更添波浪向人间。
6 */
7 #include <iostream>
8 #include <cstdio>
9 #include <algorithm>
10 #include <cstring>
11 #include <vector>
12 #include <utility>
13 #include <iomanip>
14 #include <string>
15 #include <cmath>
16 #include <queue>
17 #include <assert.h>
18 #include <map>
19 #include <ctime>
20 #include <cstdlib>
21 #include <stack>
22 #define LOCAL
23 const int INF = 0x7fffffff;
24 const int MAXN = 10000 + 10;
25 const int maxnode = 1000000;
26 const int maxm= 30000 * 2 + 10;
27 using namespace std;
28
29 struct Link_Cut_Tree{
30 struct Node{
31 int delta;//翻转标记
32 int val;//用来debug
33 Node *parent;
34 Node *ch[2];
35 }node[MAXN], *cur, _nill, *nill;
36 Node *tmp[MAXN];
37
38 bool is_root(Node* t){//判断是否是splay的根
39 if (t == nill || (t->parent->ch[0] != t && t->parent->ch[1] != t)) return 1;
40 return 0;
41 }
42 //这种题还要打标记...
43 void pushdown(Node *t){
44 if (t == nill) return ;
45 if (t->delta){
46 t->delta = 0;
47 if (t->ch[0] != nill) t->ch[0]->delta ^= 1;
48 if (t->ch[1] != nill) t->ch[1]->delta ^= 1;
49 swap(t->ch[0], t->ch[1]);
50 }
51 return;
52 }
53 void init(){
54 nill = &_nill;
55 _nill.val = 0;
56 _nill.parent = _nill.ch[0] = _nill.ch[1] = nill;
57
58 cur = node + 1;
59 }
60 Node* NEW(int val){
61 cur->parent = cur->ch[0] = cur->ch[1] = nill;
62 cur->delta = 0;
63 cur->val = val;
64 return cur++;
65 }
66 void rotate(Node *t, int d){
67 if (is_root(t)) return;
68 Node *p = t->parent;
69 p->ch[d ^ 1] = t->ch[d];
70 if (t->ch[d] != nill) t->ch[d]->parent = p;
71 t->parent = p->parent;
72 if (p != nill){
73 if (p->parent->ch[0] == p) p->parent->ch[0] = t;
74 else if (p->parent->ch[1] == p) p->parent->ch[1] = t;
75 }
76 t->ch[d] = p;
77 p->parent = t;
78 //update(p);真逗,什么都不要
79 }
80 //将t旋转到根
81 void splay(Node *t){
82 //标记下传
83 int cnt = 1;
84 tmp[0] = t;
85 for (Node *y = t; !is_root(y); y = y->parent) tmp[cnt++] = y->parent;
86 while (cnt) pushdown(tmp[--cnt]);
87
88 while (!is_root(t)){
89 Node *y = t->parent;
90 if (is_root(y)) rotate(t, (y->ch[0] == t));
91 else {
92 int d = (y->parent->ch[0] == y);
93 if (y->ch[d] == t) rotate(t, d ^ 1);
94 else rotate(y, d);
95 rotate(t, d);
96 }
97 }
98 }
99 Node* access(Node *t){
100 Node *p = nill;
101 while (t != nill){
102 splay(t);
103 if (p != nill) p->parent = t;
104 t->ch[1] = p;
105
106 p = t;
107 t = t->parent;
108 }
109 return p;
110 }
111 //合并u,v所在的树
112 void merge(Node *u, Node *v){
113 access(u);
114 splay(u);
115 u->delta = 1;
116 u->parent = v;
117 return;
118 }
119 void cut(Node *u, Node *v){
120 access(u)->delta ^= 1;
121 //splay(u);//转到顶上就切断v就可以了
122 access(v);
123 splay(v);
124
125 v->ch[0]->parent = nill;
126 v->ch[0] = nill;
127 return;
128 }
129 bool check(Node *u, Node *v){
130 while (u->parent != nill) u = u->parent;
131 while (v->parent != nill) v = v->parent;
132 return (u == v);
133 }
134 }splay;
135 int n, m;
136
137 void init(){
138 splay.init();
139 scanf("%d%d", &n, &m);
140 for (int i = 1; i <= n; i++){
141 splay.NEW(i);
142 }
143 }
144 void work(){
145 for (int i = 1; i <= m; i++){
146 char str[10];
147 scanf("%s", str);
148 if (str[0] == ‘C‘){
149 int u, v;
150 scanf("%d%d", &u, &v);
151 if (u == v || splay.check(splay.node + u, splay.node + v)) continue;//已经在一个集合里面了
152 splay.merge(splay.node + u, splay.node + v);
153 }else if (str[0] == ‘D‘){
154 int u, v;
155 scanf("%d%d", &u, &v);
156 if (u == v || !splay.check(splay.node + u, splay.node + v)) continue;
157 splay.cut(splay.node + u, splay.node + v);
158 }else {
159 int u, v;
160 scanf("%d%d", &u, &v);
161 if (u == v || splay.check(splay.node + u, splay.node + v)) printf("Yes\n");
162 else printf("No\n");
163 }
164 }
165 }
166
167 int main (){
168
169 init();
170 work();
171 return 0;
172 }