#include<iostream>
#include<vector>
using namespace std;
const int N = 2e5 + 5;
vector<int> E[N];
int dep[N], p[N], fp[N], pos, top[N], sz[N], son[N], root, f[N];
void Dfs1(int u, int fa,int d) {
dep[u] = d;
sz[u] = 1;
for(auto v : E[u]) {
if(v == fa)
continue;
f[v] = u;
Dfs1(v, u, d + 1);
sz[u] += sz[v];
if(!son[u] || sz[son[u]] < sz[v])
son[u] = v;
}
}
void Dfs2(int u, int fa, int sp) {
top[u] = sp;
p[u] = ++pos;
fp[pos] = u;
if(son[u])
Dfs2(son[u], u, sp);
for(auto v : E[u]) {
if(v == fa || v == son[u])
continue;
Dfs2(v, u, v);
}
}
class Node {
public:
int lc, rc, sum, lazy;
Node() {
lc = rc = sum = 0;
}
};
class Segment_tree {
#define lc(k) t[k].lc
#define rc(k) t[k].rc
#define s(k) t[k].sum
#define z(k) t[k].lazy
#define middle(a, b)((a + b) >> 1)
private:
int tot = 0;
vector<Node> t;
void up(int k) {
s(k) = s(lc(k)) + s(rc(k));
}
void down(int k, int L, int R) {
if(z(k)) {
int mid = middle(L, R);
z(lc(k)) += z(k);
z(rc(k)) += z(k);
s(lc(k)) += z(k) *(mid - L + 1);
s(rc(k)) += z(k) *(R - mid);
z(k) = 0;
}
}
public:
explicit Segment_tree() = default;
void Open(int n) {
t.resize(2 * n + 14);
}
void Modify(int &k, int l, int r, int L, int R) {
if(!k)
k = ++tot;
if(l <= L && R <= r) {
++s(k);
++z(k);
return;
}
if(L == R)
return;
down(k, L, R);
int mid = middle(L, R);
if(l <= mid)
Modify(lc(k), l, r, L, mid);
if(r > mid)
Modify(rc(k), l, r, mid + 1, R);
up(k);
}
int Query(int k, int l, int r, int L, int R) {
if(l <= L && R <= r)
return s(k);
if(L == R)
return 0;
down(k, L, R);
int mid = middle(L, R);
int ans = 0;
if(lc(k) && l <= mid)
ans += Query(lc(k), l, r, L, mid);
if(rc(k) && r > mid)
ans += Query(rc(k), l, r, mid + 1, R);
return ans;
}
}str;
template<typename T>
void swp(T &_1, T &_2) {
_1 ^= _2, _2 ^= _1, _1 ^= _2;
}
void Tc_Modify(int u, int v) {
int fu = top[u], fv = top[v];
while(fu != fv) {
if(dep[fu] < dep[fv])
swp(u, v), swp(fu, fv);
str.Modify(root, p[fu], p[u], 1, pos);
u = f[fu];
fu = top[u];
}
if(dep[u] < dep[v])
swp(u, v);
str.Modify(root, p[v] + 1, p[u], 1, pos);
}
int Tc_Query(int u, int v) {
int ans = 0;
int fu = top[u], fv = top[v];
while(fu != fv) {
if(dep[fu] < dep[fv])
swp(u, v), swp(fu, fv);
ans += str.Query(root, p[fu], p[u], 1, pos);
u = f[fu];
fu = top[u];
}
if(dep[u] < dep[v])
swp(u, v);
ans += str.Query(root, p[v] + 1, p[u], 1, pos);
return ans;
}
int main() {
#ifdef LOCAL
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
ios_base::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, q;
cin >> n >> q;
for(int i = 1; i < n; ++i) {
int u, v;
cin >> u >> v;
E[u].push_back(v);
E[v].push_back(u);
}
Dfs1(1, 0, 1);
cerr << pos << '\n';
Dfs2(1, 0, 1);
str.Open(pos);
while(q--) {
char op;
int u, v;
cin >> op >> u >> v;
if(op == 'P')
Tc_Modify(u, v);
else
cout << Tc_Query(u, v) << '\n';
}
return 0;
}