#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void rd(T &x) {
  x = 0;
  char c = getchar();
  int f = 1;
  while (!isdigit(c)) {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (isdigit(c)) x = x * 10 - '0' + c, c = getchar();
  x *= f;
}
template <class T>
inline void cmax(T &x, T y) {
  if (x < y) x = y;
}
template <class T>
inline void cmin(T &x, T y) {
  if (y < x) x = y;
}
const int N = 5e5 + 10, M = N << 1;
int n, m;
struct Tree {
  int F[M], fa[M], ch[M][2], ti[M], sz[M], ncnt;
  int dfn[M], lb[M], rb[M], id;
  void init() {
    ncnt = n;
    for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1;
  }
  int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
  void un(int x, int y, int t) {
    int fx = find(x), fy = find(y), u = ++ncnt;
    fa[u] = fa[fx] = fa[fy] = u, ti[u] = t, sz[u] = sz[fx] + sz[fy];
    ch[u][0] = fx, ch[u][1] = fy;
  }
  void dfs(int u) {
    if (!ch[u][0]) {
      lb[u] = rb[u] = dfn[u] = ++id;
    } else {
      lb[u] = id + 1;
      dfs(ch[u][0]), dfs(ch[u][1]);
      F[ch[u][0]] = F[ch[u][1]] = u;
      rb[u] = id;
    }
  }
  void build() {
    for (int i = 1; i <= ncnt; ++i)
      if (find(i) == i) dfs(i);
    for (int i = 1; i <= n; ++i) fa[i] = i;
  }
  int get(int x, int t) {
    while (F[fa[x]] && ti[F[fa[x]]] <= t) fa[x] = F[fa[x]];
    return fa[x];
  }
} A, B;
namespace seg {
int cov[N << 2];
inline void push_down(int c) {
  if (cov[c]) {
    cmax(cov[c << 1], cov[c]);
    cmax(cov[c << 1 | 1], cov[c]);
    cov[c] = 0;
  }
}
void upd(int l, int r, int c, int L, int R, int v) {
  if (L <= l && R >= r) return (void)(cov[c] = v);
  int mid = l + r >> 1;
  push_down(c);
  if (L <= mid) upd(l, mid, c << 1, L, R, v);
  if (R > mid) upd(mid + 1, r, c << 1 | 1, L, R, v);
}
int query(int l, int r, int c, int v) {
  if (l == r) return cov[c];
  int mid = l + r >> 1;
  push_down(c);
  if (v <= mid)
    return query(l, mid, c << 1, v);
  else
    return query(mid + 1, r, c << 1 | 1, v);
}
}  // namespace seg
namespace Bit {
long long c[N];
void add(int i, int t) {
  for (; i <= n; i += i & -i) c[i] += t;
}
void add(int l, int r, int t) { add(l, t), add(r + 1, -t); }
long long query(int i) {
  long long ans = 0;
  for (; i; i -= i & -i) ans += c[i];
  return ans;
}
}  // namespace Bit
struct OPT {
  int ty, t, x;
  OPT(int ty = 0, int t = 0, int x = 0) : ty(ty), t(t), x(x) {}
};
vector<OPT> Q;
long long ans[N];
struct Que {
  int p, id, sgn;
  Que(int p = 0, int id = 0, int sgn = 0) : p(p), id(id), sgn(sgn) {}
};
vector<Que> R[N];
char ty[20];
int main() {
  rd(n), rd(m);
  A.init(), B.init();
  for (int i = 1, x, y; i <= m; ++i) {
    scanf("%s", ty);
    if (ty[0] == 'U') {
      rd(x), rd(y);
      A.un(x, y, i);
    } else if (ty[0] == 'M') {
      rd(x), rd(y);
      B.un(x, y, i);
    } else {
      rd(x);
      Q.push_back(OPT(ty[0] == 'A' ? 1 : (ty[0] == 'Z' ? 2 : 3), i, x));
    }
  }
  A.build(), B.build();
  int qtot = 0;
  for (int i = 0; i < Q.size(); ++i)
    if (Q[i].ty == 2) {
      int x = B.get(Q[i].x, Q[i].t);
      seg::upd(1, n, 1, B.lb[x], B.rb[x], Q[i].t);
    } else if (Q[i].ty == 3) {
      R[Q[i].t].push_back(Que(A.dfn[Q[i].x], ++qtot, 1));
      int pre = seg::query(1, n, 1, B.dfn[Q[i].x]);
      if (pre) R[pre].push_back(Que(A.dfn[Q[i].x], qtot, -1));
    }
  int q = 0;
  for (int i = 1; i <= m; ++i) {
    while (q < Q.size() && Q[q].t <= i) {
      if (Q[q].ty == 1) {
        int anc = A.get(Q[q].x, Q[q].t);
        Bit::add(A.lb[anc], A.rb[anc], A.sz[anc]);
      }
      q++;
    }
    for (int j = 0; j < R[i].size(); ++j)
      ans[R[i][j].id] += R[i][j].sgn * Bit::query(R[i][j].p);
  }
  for (int i = 1; i <= qtot; ++i) printf("%lld\n", ans[i]);
  return 0;
}
