#include <bits/stdc++.h>
using namespace std;
const int kN = 5e5 + 5, kS = kN << 1;
struct QueryType {
  char opt;
  int x, y;
} q[kN];
int n, m, cnt, cur[kN];
long long ans[kN];
vector<QueryType> last_raid[kN];
struct ufSet {
  int fa[kS], siz[kS], elem, time_stamp[kS];
  long long delta[kS];
  void Reset() {
    for (int i = 1; i <= n * 2; ++i) {
      fa[i] = i;
      siz[i] = 1;
    }
    for (int i = 1; i <= n; ++i) cur[i] = i;
    elem = n;
  }
  int Find(int x) {
    if (fa[x] == fa[fa[x]]) return fa[x];
    int fx = Find(fa[x]);
    time_stamp[x] = max(time_stamp[fa[x]], time_stamp[x]);
    delta[x] += delta[fa[x]];
    return fa[x] = fx;
  }
  int Merge(int x, int y) {
    siz[++elem] = siz[x] + siz[y];
    return fa[x] = fa[y] = elem;
  }
  long long Query(int x) {
    Find(x);
    if (x == fa[x]) return delta[x];
    return delta[x] + delta[fa[x]];
  }
} uf;
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; ++i) {
    static char str[5];
    scanf("%s%d", str, &q[i].x);
    q[i].opt = str[0];
    if (str[0] == 'U' || str[0] == 'M')
      scanf("%d", &q[i].y);
    else if (str[0] == 'Q')
      q[i].y = ++cnt;
  }
  uf.Reset();
  for (int i = 1; i <= m; ++i) {
    if (q[i].opt == 'M')
      cur[q[i].x] = uf.Merge(cur[q[i].x], cur[q[i].y]);
    else if (q[i].opt == 'Z')
      uf.time_stamp[cur[q[i].x]] = i;
    else if (q[i].opt == 'Q') {
      last_raid[max(uf.time_stamp[q[i].x], uf.time_stamp[uf.Find(q[i].x)])]
          .push_back(q[i]);
    }
  }
  uf.Reset();
  for (int i = 1; i <= m; ++i) {
    if (q[i].opt == 'U')
      cur[q[i].x] = uf.Merge(cur[q[i].x], cur[q[i].y]);
    else if (q[i].opt == 'A')
      uf.delta[cur[q[i].x]] += uf.siz[cur[q[i].x]];
    else if (q[i].opt == 'Q')
      ans[q[i].y] += uf.Query(q[i].x);
    for (const auto &now : last_raid[i]) ans[now.y] -= uf.Query(now.x);
  }
  for (int i = 1; i <= cnt; ++i) printf("%lld\n", ans[i]);
  return 0;
}
