#include <bits/stdc++.h>
using namespace std ;
const int N = 2e5 ;
inline int read() {
int x = 0 , f = 1 ;
char c = getchar() ;
while (c < '0' || c > '9') {
if (c == '-') f = -f ;
c = getchar() ;
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
#ifndef Scapegoat_Tree
#define lson(x) t[x].son[0]
#define rson(x) t[x].son[1]
#define Size(x) t[x].Size
#define value(x) t[x].value
#define Cnt(x) t[x].cnt
struct _Point {
int son[2] , Size , value ;
int cnt ;
} t[N * 45] ;
int numbol ; int tot , chain[N] ;
const double alpha = 0.75 ;
void Getchain(int x) {
if (!x) return ;
if (t[x].cnt) chain[++ tot] = x ;
Getchain(lson(x)) , Getchain(rson(x)) ;
}
inline void push_up(int x) {
t[x].Size = Size(lson(x)) + Size(rson(x)) + Cnt(x) ;
}
int build(int l , int r) {
if (l == r) return 0 ;
int mid = (l + r) >> 1 ;
lson(chain[mid]) = build(l , mid) ;
rson(chain[mid]) = build(mid + 1 , r) ;
push_up(chain[mid]) ;
return chain[mid] ;
}
void check(int x) {
if (Size(x) * alpha < max(Size(lson(x)) , Size(rson(x)))) {
tot = 0 ; Getchain(x) ;
build(1 , tot + 1) ;
}
}
void Insert(int &x , int val) {
if (!x) {
x = ++ numbol ;
Cnt(x) = 1 ; Size(x) = 1 ; value(x) = val ;
return ;
} else if (value(x) == val) return ++ Cnt(x) , void() ;
if (value(x) > val) Insert(lson(x) , val) ;
else Insert(rson(x) , val) ;
push_up(x) ; check(x) ;
}
void Erase(int &x , int val) {
Size(x) -- ;
if (value(x) == val) return -- Cnt(x) , void() ;
else if (value(x) > val) Erase(lson(x) , val) ;
else Erase(rson(x) , val) ;
push_up(x) ; check(x) ;
}
int Find(int x , int k) {
while (114514) {
if (k <= Cnt(x) + Size(lson(x))) return value(x) ;
else if (Size(lson(x)) >= k) x = lson(x) ;
else k -= Cnt(x) + Size(lson(x)) , x = rson(x) ;
}
}
#undef lson
#undef rson
#undef value
#undef Size
#endif
#ifndef SEGMENT_TREE
#define lson (id << 1)
#define rson (id << 1 | 1)
#define mid ((l + r) >> 1)
int ts[N << 2] ;
void updata(int id , int l , int r , int x , int c) {
if (l == r) return ts[id] = c , void() ;
if (x <= mid) updata(lson , l , mid , x , c) ;
else updata(rson , mid + 1 , r , x , c) ;
ts[id] = max(ts[lson] , ts[rson]) ;
}
#undef lson
#undef rson
#undef mid
#endif
int n , m , Size[N] , top[N] , son[N] , heavy[N] , depth[N] ;
int root ; bool vis[N] , color[N] ; int all[N] , s[N] , father[N] ;
struct EGDE {
int next , to ;
} e[N << 1] , e1[N << 1] ; int head[N] , head1[N] , cnt1 , cnt ;
inline void add(int x , int y) {
cnt ++ ; e[cnt].next = head[x] , e[cnt].to = y , head[x] = cnt ;
}
inline void add1(int x , int y) {
cnt1 ++ ; e1[cnt1].next = head1[x] , e[cnt1].to = y ; head1[x] = cnt1 ;
}
inline int LCA(int x , int y) {
int topper_x = top[x] , topper_y = top[y] ;
while (topper_x != topper_y) {
if (depth[topper_x] >= depth[topper_y]) {
x = father[topper_x] ;
} else y = father[topper_y] ;
}
return depth[x] >= depth[y] ? y : x ;
}
inline int dis(int x , int y) {
return depth[x] + depth[y] - 2 * depth[LCA(x , y)] ;
}
void dfs1(int x , int fa) {
Size[x] = 1 ; son[x] = 0 ;
for (int i = head[x] ; i ; i = e[i].next) {
int y = e[i].to ;
if (y != fa && !vis[y]) {
dfs1(y , x) , Size[x] += Size[y] ;
son[x] = max(son[x] , Size[y]) ;
}
}
son[x] = max(son[x] , Tree_Size - Size[x]) ;
if (son[x] < son[root]) root = x ;
}
void dfs_dep(int x , int fa) {
depth[x] = depth[fa] + 1 ;
for (int i = head[x] ; i ; i = e[i].next) {
int y = e[i].to ;
if (y != fa) {
dfs_dep(y , x) ;
if (Size[y] > Size[heavy[x]]) heavy[x] = y ;
}
}
}
void dfs_top(int x , int crown) {
top[x] = crown ;
if (heavy[x]) dfs_top(heavy[x] , crown) ;
for (int i = head[x] ; i ; i = e[i].next) {
int y = e[i].to ;
if (y != fa && y != heavy[x])
dfs_top(y , y) ;
}
}
void dfs_build(int x) {
vis[x] = 1 ;
for (int i = head[x] ; i ; i = e[i].next) {
int y = e[i].to ;
if (!vis[y]) {
root = 0 ; dfs1(y , 0) ; father[root] = x ;
add1(x , root) ; dfs_build(root) ;
}
}
}
void dfs_goat(int x , int now) {
Insert(all[now] , dis(now , x)) ;
for (int i = head1[x] ; i ; i = e[i].next) {
int y = e1[i].to ;
dfs_goat(y , now) ;
}
}
void dfs_set(int x) {
for (int i = head1[x] ; i ; i = e1[i].next) {
int y = e1[i].to ;
dfs_goat(y , x) , dfs_set(y) ;
Insert(s[x] , Find(all[y] , Size(all[y]))) ;
}
Insert(s[x] , 0) , Insert(all[x] , 0) ;
}
void Delete(int x , int pos) {
if (!x) return ;
int last = Find(all[x] , Size(all[x])) ;
Erase(all[x] , dis(x , pos)) ;
int now = Find(all[x] , Size(all[x])) ;
if (father[x]) {
int fa = father[x] ;
Erase(s[fa] , last) ; Insert(s[fa] , now) ;
}
if (Size(all[x])) {
updata(1 , 1 , n , x , Find(s[x] , Size(s[x])) + Find(s[x] , Size(s[x]) - 1)) ;
} else updata(1 , 1 , n , x , 0) ;
Delete(father[x] , pos) ;
}
void Modify(int x , int pos) {
if (!x) return ;
int last = Find(all[x] , Size(all[x])) ;
Insert(all[x] , dis(x , pos)) ;
int now = Find(all[x] , Size(all[x])) ;
if (father[x]) {
int fa = father[x] ;
Erase(s[fa] , last) , Insert(s[fa] , now) ;
}
updata(1 , 1 , n , x , Find(s[x] , Size(s[x])) + Find(s[x] , Size(s[x]) - 1)) ;
Modify(father[x] , pos) ;
}
char opt ; int num ;
signed main() {
#ifndef ONLINE_JUDGE
freopen("1.in" , "r" , stdin) ;
freopen("1.out" , "w" , stdout) ;
#endif
n = read() , num = n ;
for (int i = 1 , x , y ; i < n ; ++ i) {
x = read() , y = read() ;
add(x , y) , add(y , x) ;
}
auto Getcher = []() {
char c = getchar() ;
while (c != 'G' && c != 'C') c = getchar() ;
return c ;
} ;
dfs_dep(1 , 0) ; dfs_top(1 , 1) ;
root = 0 ; son[0] = 0x7f7f7f7f ;
dfs1(1 , 0) ; dfs_build(root) ;
m = read() ; int x ;
while (m --) {
opt = read() ;
if (opt == 'C') {
x = read() , color[x] ^= 1 ;
if (color[x]) {
num -- ;
Delete(x , x) ;
} else {
num ++ ;
Modify(x , x) ;
}
} else {
if (!num) cout << -1 << '\n' ;
else if (num == 1) cout << 0 << '\n' ;
else cout << ts[1] << '\n' ;
}
}
}