#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
struct edge {
  int to, next;
} e[N * 2];
int head[N], ecnt;
vector<int> G[N];
inline void adde(int from, int to) {
  e[++ecnt] = (edge){to, head[from]}, head[from] = ecnt;
  e[++ecnt] = (edge){from, head[to]}, head[to] = ecnt;
}
inline void adde2(int from, int to) {
  G[from].push_back(to), G[to].push_back(from);
}
int dfn[N], ed[N], dfsn;
void dfs(int u, int f) {
  dfn[u] = ++dfsn;
  for (int i = head[u]; i; i = e[i].next)
    if (e[i].to != f) dfs(e[i].to, u);
  ed[u] = dfsn;
}
int dfn2[N], ed2[N], dfsn2;
void dfs2(int u, int f) {
  dfn2[u] = ++dfsn2;
  for (auto v : G[u])
    if (v != f) dfs2(v, u);
  ed2[u] = dfsn2;
}
long long tree[N];
inline void update(int x, int y) {
  for (; x <= dfsn; x += x & -x) tree[x] += y;
}
inline long long query(int x) {
  long long res = 0;
  for (; x; x -= x & -x) res += tree[x];
  return res;
}
struct Tree {
  int tag[N << 2];
  void update(int rt, int l, int r, int start, int end, int x) {
    if (start <= l && r <= end) return tag[rt] = x, void();
    if (tag[rt])
      return tag[rt << 1] = tag[rt << 1 | 1] = tag[rt], tag[rt] = 0, void();
    int mid = (l + r) >> 1;
    if (start <= mid) update(rt << 1, l, mid, start, end, x);
    if (end > mid) update(rt << 1 | 1, mid + 1, r, start, end, x);
  }
  int query(int rt, int l, int r, int at) {
    if (l == r || tag[rt]) return tag[rt];
    int mid = (l + r) >> 1;
    if (at <= mid) return query(rt << 1, l, mid, at);
    return query(rt << 1 | 1, mid + 1, r, at);
  }
} T;
struct Query {
  char op[2];
  int a, b, at;
} q[N];
int fa[N], fa2[N], sz[N], ncnt, ncnt2;
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
int find2(int x) { return x == fa2[x] ? x : fa2[x] = find2(fa2[x]); }
int at[N], at2[N];
vector<int> fuck[N];
long long ans[N];
int main() {
  int n, m;
  scanf("%d%d", &n, &m), ncnt = ncnt2 = n;
  for (int i = 1; i <= n; i++) fa[i] = fa2[i] = at[i] = at2[i] = i, sz[i] = 1;
  for (int i = 1; i <= m; i++) {
    scanf("%s%d", q[i].op, &q[i].a);
    if (q[i].op[0] == 'U') {
      scanf("%d", &q[i].b);
      int u = find(q[i].a), v = find(q[i].b), t = ++ncnt;
      adde(t, at[u]), adde(t, at[v]), fa[v] = u, at[u] = t, sz[u] += sz[v];
    } else if (q[i].op[0] == 'M') {
      scanf("%d", &q[i].b);
      int u = find2(q[i].a), v = find2(q[i].b), t = ++ncnt2;
      adde2(t, at2[u]), adde2(t, at2[v]), fa2[v] = u, at2[u] = t;
    } else if (q[i].op[0] == 'Z') {
      q[i].at = at2[find2(q[i].a)];
    } else if (q[i].op[0] == 'A') {
      q[i].at = at[find(q[i].a)], q[i].b = sz[find(q[i].a)];
    }
  }
  for (int i = 1; i <= n; i++)
    if (find(i) == i) dfs(at[i], 0);
  for (int i = 1; i <= n; i++)
    if (find2(i) == i) dfs2(at2[i], 0);
  for (int i = 1; i <= m; i++) {
    if (q[i].op[0] == 'Z')
      T.update(1, 1, dfsn2, dfn2[q[i].at], ed2[q[i].at], i);
    if (q[i].op[0] == 'Q')
      fuck[T.query(1, 1, dfsn2, dfn2[q[i].a])].push_back(i);
  }
  for (int i = 1; i <= m; i++) {
    if (q[i].op[0] == 'A') {
      int u = q[i].at, x = q[i].b;
      update(dfn[u], x), update(ed[u] + 1, -x);
    }
    for (auto t : fuck[i]) ans[t] -= query(dfn[q[t].a]);
    if (q[i].op[0] == 'Q') ans[i] += query(dfn[q[i].a]);
  }
  for (int i = 1; i <= m; i++)
    if (q[i].op[0] == 'Q') printf("%lld\n", ans[i]);
  return 0;
}
