(\ \テキスト{この問題は、分割木ストランドボードタイトルである(木が速くLCTより実行断面として)} \)
(\ \テキスト{動作この問題:変更されたゾーンのセクションクエリ} \)
\(\テキスト\ {我々は問題は、我々が直接乾燥重量を判断しないように、xの一切の繰り返しがないと考えます})
(\ \テキスト{即ち、これを直接クエリを終了存在する各加算器戦争ベクターの操作..} \)
\(\ {テキストはいいいえクエリー間隔は確かにある戦争上の位置を取得している場合ではないクエリで0} \)
\(\ mathcalコード\)
//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '\n') { int tp = 0 ;
if(x == 0) return (void) puts("0") ;
if(x < 0) putchar('-') , x = -x ;
for( ; x ; x /= 10) st[++ tp] = x % 10 ;
for( ; tp ; tp --) putchar(st[tp] + '0') ;
putchar(c) ;
}
//#define Online_Judge
int n ;
vector < pair < int , int > > v ;
const int N = 3e5 + 10 ;
int a[N] ;
struct node {
int v ;
int nxt ;
};
node e[N << 1] ; int head[N] ;
int cnt = 0 ;
inline void Add(int u , int v) {
e[++ cnt].v = v ;
e[cnt].nxt = head[u] ;
head[u] = cnt ;
return ;
}
int size[N] ;
int top[N] , son[N] ;
int fa[N] ; int id[N] ; int d[N] ;
int idx = 0 ;
inline void Dfs1(int u) {
size[u] = 1 ;
for(register int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ;
if(v ^ fa[u]) {
fa[v] = u ;
d[v] = d[u] + 1 ;
Dfs1(v) ;
size[u] += size[v] ;
if(size[son[u]] < size[v]) son[u] = v ;
}
}
}
inline void Dfs2(int u , int t) {
id[u] = ++ idx ;
top[u] = t ;
a[idx] = 0 ;
if(! son[u]) return ;
Dfs2(son[u] , t) ;
for(register int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ;
if(v ^ fa[u] && v ^ son[u]) {
Dfs2(v , v) ;
}
}
}
int sum[N << 2] ;
int tag[N << 2] ;
inline void build(int l , int r , int rt) {
if(l == r) {
sum[rt] = a[l] ;
tag[rt] = 0 ;
return ;
}
int mid = l + r >> 1 ;
build(l , mid , rt << 1) ;
build(mid + 1 , r , rt << 1 | 1) ;
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] ;
return ;
}
inline void Push_down(int rt , int l , int r) {
if(tag[rt]) {
tag[rt << 1] += tag[rt] ;
tag[rt << 1 | 1] += tag[rt] ;
int mid = l + r >> 1 ;
sum[rt << 1] += tag[rt] * (mid - l + 1) ;
sum[rt << 1 | 1] += tag[rt] * (r - mid) ;
tag[rt] = 0 ;
return ;
}
}
inline void Change(int a , int b , int l , int r , int rt , int val) {
if(a <= l && r <= b) {
sum[rt] += val * (r - l + 1) ;
tag[rt] += val ;
return ;
}
int mid = l + r >> 1 ;
Push_down(rt , l , r) ;
if(a <= mid) Change(a , b , l , mid , rt << 1 , val) ;
if(b > mid) Change(a , b , mid + 1 , r , rt << 1 | 1 , val) ;
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] ;
return ;
}
inline int Query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return sum[rt] ;
int mid = l + r >> 1 ;
int ans = 0 ;
Push_down(rt , l , r) ;
if(a <= mid) ans += Query(a , b , l , mid , rt << 1) ;
if(b > mid) ans += Query(a , b , mid + 1 , r , rt << 1 | 1) ;
return ans ;
}
inline int Query_Range(int x , int y) {
int fx = top[x] ;
int fy = top[y] ;
int ans = 0 ;
while(fx ^ fy) {
if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
ans += Query(id[fx] , id[x] , 1 , n , 1) ;
x = fa[fx] ;
fx = top[x] ;
}
if(id[x] > id[y]) swap(x , y) ;
ans += Query(id[x] + 1 , id[y] , 1 , n , 1) ;
return ans ;
}
inline void Change_Range(int x , int y , int val) {
int fx = top[x] ;
int fy = top[y] ;
int ans = 0 ;
while(fx ^ fy) {
if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
Change(id[fx] , id[x] , 1 , n , 1 , val) ;
x = fa[fx] ;
fx = top[x] ;
}
if(id[x] > id[y]) swap(x , y) ;
Change(id[x] + 1 , id[y] , 1 , n , 1 , val) ;
}
signed main() {
#ifdef Online_Judge
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata2.out" , "w" , stdout) ;
#endif
n = read() ; int q = read() ;
for(register int i = 1 ; i <= n - 1 ; i ++) {
int u = read() ;
int v = read() ;
Add(u , v) ;
Add(v , u) ;
}
Dfs1(1) ;
Dfs2(1 , 1) ;
build(1 , n , 1) ;
for(register int i = 1 ; i <= q ; i ++) {
register char c = getchar() ;
for( ; c != 'C' && c != 'Q' && c != 'U' ; c = getchar()) ;
if(c == 'Q') {
int x = read() , y = read() ;
if(Query_Range(x , y)) puts("No") ;
else puts("Yes") ;
}
if(c == 'C') {
int x = read() , y = read() ;
Change_Range(x , y , 1) ;
v.push_back(make_pair(x , y)) ;
}
if(c == 'U') {
int num = read() - 1 ;
int x = v[num].first ;
int y = v[num].second ;
Change_Range(x , y , - 1) ;
}
}
return 0 ;
}