#include <bits/stdc++.h>
using namespace std;
const int MAXN = int(5e5 + 100);
vector<int> mg[MAXN];
int mlpos[MAXN], mrpos[MAXN];
int mtin[MAXN];
int mendtime[MAXN];
char s[100];
struct query {
  char type;
  int a, b;
};
void mdfs(int v, int par, int& timer) {
  if (v == par) {
    ++timer;
    mtin[v] = timer;
    return;
  }
  for (auto to : mg[v]) mdfs(to, v, timer);
}
vector<int> mt[4 * MAXN];
void mt_add(int tv, int tl, int tr, int l, int r, int time) {
  if (l > r) return;
  if (tl == l && tr == r) {
    mt[tv].push_back(time);
    return;
  }
  int tm = (tl + tr) / 2;
  mt_add(2 * tv, tl, tm, l, min(tm, r), time);
  mt_add(2 * tv + 1, tm + 1, tr, max(tm + 1, l), r, time);
}
int mt_last(int tv, int tl, int tr, int pos, int ub) {
  auto it = upper_bound(mt[tv].begin(), mt[tv].end(), ub);
  int res = it == mt[tv].begin() ? 0 : *(--it);
  if (tl == tr) return res;
  int tm = (tl + tr) / 2;
  int sub_res = 0;
  if (pos <= tm)
    sub_res = mt_last(2 * tv, tl, tm, pos, ub);
  else
    sub_res = mt_last(2 * tv + 1, tm + 1, tr, pos, ub);
  return max(res, sub_res);
}
int uendtime[MAXN];
int usize[MAXN];
vector<int> ug[MAXN];
vector<int> ua[MAXN];
vector<int> uatime[MAXN];
vector<int> uq[MAXN];
long long qres[MAXN];
void u_dfs(int v, int n, vector<int>& atime, vector<long long>& asum) {
  for (int i = int(ua[v].size()) - 1; i >= 0; --i) {
    atime.push_back(uatime[v][i]);
    asum.push_back((asum.empty() ? 0 : asum.back()) + ua[v][i]);
  }
  if (!asum.empty())
    for (int q : uq[v]) {
      auto it1 = lower_bound(atime.begin(), atime.end(), q, greater<int>());
      int pos1 = distance(atime.begin(), it1);
      long long sum1 = asum.back() - (pos1 ? asum[pos1 - 1] : 0);
      long long t2 = mt_last(1, 1, n, mtin[v], q);
      auto it2 = lower_bound(atime.begin(), atime.end(), t2, greater<int>());
      int pos2 = distance(atime.begin(), it2);
      long long sum2 = asum.back() - (pos2 ? asum[pos2 - 1] : 0);
      long long sum = sum1 - sum2;
      qres[q] = sum;
    }
  for (int to : ug[v]) {
    while (!atime.empty() && atime.back() < uendtime[to]) {
      atime.pop_back();
      asum.pop_back();
    }
    u_dfs(to, n, atime, asum);
  }
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  vector<query> qs(m + 1);
  for (int i = 1; i <= m; ++i) {
    scanf("%s", s);
    qs[i].type = *s;
    if (qs[i].type == 'U' || qs[i].type == 'M')
      scanf("%d%d", &qs[i].a, &qs[i].b);
    else
      scanf("%d", &qs[i].a);
  }
  for (int i = 1; i <= n; ++i) {
    mg[i].push_back(i);
    mendtime[i] = m + 1;
  }
  for (int i = 1; i <= m; ++i)
    if (qs[i].type == 'M') {
      mg[qs[i].a].push_back(qs[i].b);
      mendtime[qs[i].b] = i;
    }
  int mtimer = 0;
  for (int i = 1; i <= n; ++i)
    if (mendtime[i] == m + 1) mdfs(i, -1, mtimer);
  for (int i = 1; i <= n; ++i) mlpos[i] = mrpos[i] = mtin[i];
  for (int i = 1; i <= m; ++i) {
    int a = qs[i].a;
    int b = qs[i].b;
    if (qs[i].type == 'M') {
      mlpos[a] = min(mlpos[a], mlpos[b]);
      mrpos[a] = max(mrpos[a], mrpos[b]);
    } else if (qs[i].type == 'Z') {
      mt_add(1, 1, n, mlpos[a], mrpos[a], i);
    }
  }
  for (int i = 1; i <= n; ++i) usize[i] = 1;
  for (int i = 1; i <= m; ++i) {
    int a = qs[i].a;
    int b = qs[i].b;
    if (qs[i].type == 'U') {
      uendtime[b] = i;
      usize[a] += usize[b];
      ug[a].push_back(b);
    } else if (qs[i].type == 'A') {
      ua[a].push_back(usize[a]);
      uatime[a].push_back(i);
    } else if (qs[i].type == 'Q') {
      uq[a].push_back(i);
    }
  }
  vector<int> atime;
  vector<long long> asum;
  for (int i = 1; i <= n; ++i)
    if (uendtime[i] == 0) {
      atime.clear();
      asum.clear();
      u_dfs(i, n, atime, asum);
    }
  for (int i = 1; i <= m; ++i)
    if (qs[i].type == 'Q') printf("%lld\n", qres[i]);
  return 0;
}
