#include <bits/stdc++.h>
using namespace std;
struct query {
  int op, x, y;
} q[500050];
int n, m, qt;
long long ans[500050];
vector<query> q1[500050];
inline void read(int&), get(char&), Max(int&, int);
struct union_find {
  int fa[500050], sz[500050], tag[500050];
  inline void init() {
    for (int i(1); i <= n; ++i) fa[i] = i, sz[i] = 1;
  }
  inline int find(int x) {
    if (x == fa[x]) return x;
    int rt(find(fa[x]));
    Max(tag[x], tag[fa[x]]);
    return fa[x] = rt;
  }
  inline void Union(int u, int v) {
    u = find(u), v = find(v);
    if (tag[u] < tag[v]) u ^= v ^= u ^= v;
    sz[v] += sz[u], fa[u] = v;
  }
  inline int ask(int x) {
    int temp(tag[find(x)]);
    return temp < tag[x] ? tag[x] : temp;
  }
} U;
struct union_find1 {
  long long tag[500050];
  int fa[500050], sz[500050];
  inline void init() {
    for (int i(1); i <= n; ++i) fa[i] = i, sz[i] = 1;
  }
  inline int find(int x) {
    if (x == fa[x]) return x;
    int rt(find(fa[x]));
    if (fa[x] == rt) return rt;
    tag[x] += tag[fa[x]];
    return fa[x] = rt;
  }
  inline void Union(int u, int v) {
    u = find(u), v = find(v);
    if (sz[u] > sz[v]) u ^= v ^= u ^= v;
    sz[v] += sz[u], fa[u] = v, tag[u] -= tag[v];
  }
  inline long long ask(int x) {
    if (x == fa[x]) return tag[x];
    long long temp(tag[find(x)]);
    return temp + tag[x];
  }
} U1;
int main() {
  read(n), read(m);
  for (int i(1); i <= m; ++i) {
    char c;
    switch (get(c), c) {
      case 'U':
        q[i].op = 1, read(q[i].x), read(q[i].y);
        break;
      case 'M':
        q[i].op = 2, read(q[i].x), read(q[i].y);
        break;
      case 'A':
        q[i].op = 3, read(q[i].x);
        break;
      case 'Z':
        q[i].op = 4, read(q[i].x);
        break;
      case 'Q':
        q[i].op = 5, read(q[i].x), q[i].y = ++qt;
        break;
    }
  }
  U.init(), U1.init();
  for (int i(1), i1; i <= m; ++i)
    if (q[i].op == 2)
      U.Union(q[i].x, q[i].y);
    else if (q[i].op == 4)
      Max(U.tag[U.find(q[i].x)], i);
    else if (q1[i].push_back(q[i]), q[i].op == 5)
      if (i1 = U.ask(q[i].x)) q1[i1].push_back(q[i]);
  for (int i(1), j, i1; i <= m; ++i)
    for (j = 0; j < q1[i].size(); ++j) {
      query& q2(q1[i][j]);
      switch (q2.op) {
        case 1:
          U1.Union(q2.x, q2.y);
          break;
        case 3:
          i1 = U1.find(q2.x), U1.tag[i1] += U1.sz[i1];
          break;
        case 5:
          ans[q2.y] = U1.ask(q2.x) - ans[q2.y];
          break;
      }
    }
  for (int i(1); i <= qt; ++i) printf("%lld\n", ans[i]);
  return 0;
}
inline void get(char& c) {
  while (c = getchar(), c == ' ' || c == '\n' || c == '\r')
    ;
}
inline void read(int& x) {
  x ^= x;
  register char c;
  while (c = getchar(), c < '0' || c > '9')
    ;
  while (c >= '0' && c <= '9')
    x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
}
inline void Max(int& x, int y) { x = x > y ? x : y; }
