#include <bits/stdc++.h>
using namespace std;
const int __SIZE = 1 << 18;
char ibuf[__SIZE], *iS, *iT;
template <typename T>
inline void read(T &x) {
  char ch, t = 0;
  x = 0;
  while (!isdigit(ch = (iS == iT
                            ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                               (iS == iT ? EOF : *iS++))
                            : *iS++)))
    t |= ch == '-';
  while (isdigit(ch))
    x = x * 10 + (ch ^ 48),
    ch = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                      (iS == iT ? EOF : *iS++))
                   : *iS++);
  x = t ? -x : x;
}
inline char read_alpha() {
  char c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                        (iS == iT ? EOF : *iS++))
                     : *iS++);
  while (!isalpha(c) && c != EOF)
    c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin),
                     (iS == iT ? EOF : *iS++))
                  : *iS++);
  return c;
}
inline int read_int() {
  int x;
  return read(x), x;
}
inline long long read_ll() {
  long long x;
  return read(x), x;
}
template <typename T>
inline void chkmin(T &a, T b) {
  a = a < b ? a : b;
}
template <typename T>
inline void chkmax(T &a, T b) {
  a = a > b ? a : b;
}
const int MAXN = 1000010;
int n, q;
struct Bit {
  int N;
  long long T[MAXN];
  inline void Add(int p, long long v) {
    while (p <= N) T[p] += v, p += p & -p;
  }
  inline void Modify(int l, int r, int v) { Add(l, v), Add(r + 1, -v); }
  inline long long Q(int p) {
    long long v = 0;
    while (p) v += T[p], p ^= p & -p;
    return v;
  }
} bit;
struct Segment_Tree {
  int T[MAXN << 2];
  inline void Modify(int x, int l, int r, int L, int R, int v) {
    if (L <= l && r <= R) return T[x] = v, void();
    int mid = (l + r) >> 1;
    if (L <= mid) Modify((x << 1), l, mid, L, R, v);
    if (mid < R) Modify((x << 1 | 1), mid + 1, r, L, R, v);
  }
  inline int Q(int x, int l, int r, int p) {
    if (T[x] || l == r) return T[x];
    int mid = (l + r) >> 1;
    return p <= mid ? Q((x << 1), l, mid, p) : Q((x << 1 | 1), mid + 1, r, p);
  }
} seg;
struct Tree {
  int N;
  struct UFS {
    int fa[MAXN];
    int sz[MAXN];
    inline void init() {
      for (int i = 1; i <= n + q; i++) fa[i] = i, sz[i] = i <= n;
    }
    inline int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
    inline int size(int x) { return sz[find(x)]; }
    inline void Merge(int x, int y) {
      x = find(x), y = find(y);
      if (x == y) return;
      fa[y] = x, sz[x] += sz[y];
    }
  } ufs;
  int L[MAXN];
  int R[MAXN];
  inline int Qfa(int x) { return ufs.find(x); }
  inline int Qsize(int x) { return ufs.size(x); }
  inline void Merge(int x, int y) {
    ++N;
    L[N] = ufs.find(x);
    R[N] = ufs.find(y);
    ufs.Merge(N, x);
    ufs.Merge(N, y);
  }
  int dfn[MAXN];
  int las[MAXN];
  int tim;
  inline void dfs(int x) {
    dfn[x] = ++tim;
    if (L[x]) dfs(L[x]);
    if (R[x]) dfs(R[x]);
    las[x] = tim;
  }
  inline void Prework() {
    for (int i = 1; i <= N; i++)
      if (ufs.find(i) == i) dfs(i);
  }
} A, B;
struct Opeartor {
  int op, x, y;
  inline void rd() {
    char c = read_alpha();
    switch (c) {
      case 'U':
        op = 1;
        x = read_int();
        y = read_int();
        A.Merge(x, y);
        break;
      case 'M':
        op = 2;
        x = read_int();
        y = read_int();
        B.Merge(x, y);
        break;
      case 'A':
        op = 3;
        x = A.Qfa(read_int());
        y = A.Qsize(x);
        break;
      case 'Z':
        op = 4;
        x = B.Qfa(read_int());
        break;
      case 'Q':
        op = 5;
        x = read_int();
        break;
    }
  }
} op[MAXN];
long long res[MAXN];
struct Query {
  int t, p, id;
  Query() {}
  Query(int t, int p, int id) : t(t), p(p), id(id) {}
  inline int sgn() { return t == id ? 1 : -1; }
  friend bool operator<(Query a, Query b) { return a.t < b.t; }
} Q[MAXN];
int main() {
  n = read_int(), q = read_int();
  A.N = B.N = n;
  A.ufs.init(), B.ufs.init();
  for (int i = 1; i <= q; i++) op[i].rd();
  A.Prework(), B.Prework(), bit.N = A.N;
  int qry = 0, now = 0;
  for (int i = 1; i <= q; i++) {
    if (op[i].op == 4) seg.Modify(1, 1, B.N, B.dfn[op[i].x], B.las[op[i].x], i);
    if (op[i].op == 5) {
      int x = op[i].x;
      Q[++qry] = Query(i, x, i);
      Q[++qry] = Query(seg.Q(1, 1, B.N, B.dfn[x]), x, i);
    }
  }
  sort(Q + 1, Q + 1 + qry);
  while (!Q[now].t) ++now;
  for (int i = 1; i <= q; i++) {
    int x = op[i].x, y = op[i].y;
    if (op[i].op == 3) bit.Modify(A.dfn[x], A.las[x], y);
    while (Q[now].t == i) {
      res[Q[now].id] += Q[now].sgn() * bit.Q(A.dfn[Q[now].p]);
      ++now;
    }
  }
  for (int i = 1; i <= q; i++)
    if (op[i].op == 5) printf("%lld\n", res[i]);
  return 0;
}
