#include <bits/stdc++.h>
const int N = 5e5 + 5;
using namespace std;
int n, m, sz[N];
struct qry {
  char opt[2];
  int x, y;
  inline void rd() {
    scanf("%s%d", opt, &x);
    if (opt[0] == 'U' || opt[0] == 'M') scanf("%d", &y);
  }
} q[N];
struct Tree1 {
  int f[N << 1];
  long long val[N << 1];
  inline void init() {
    for (int i = 1; i <= n + m; i++) f[i] = i, val[i] = 0;
  }
  inline int find(int x) {
    if (x == f[x]) return x;
    int p = find(f[x]);
    if (p ^ f[x]) {
      val[x] += val[f[x]];
      f[x] = p;
    }
    return p;
  }
  inline void merge(int u, int v) {
    if ((u = find(u)) == (v = find(v))) return;
    f[u] = v;
  }
  inline void out() {
    puts("=======");
    printf("f=");
    for (int i = 1; i <= n; i++) {
      printf("%d%c", f[i], i ^ n ? ' ' : '\n');
    }
    printf("val=");
    for (int i = 1; i <= n; i++) {
      printf("%lld%c", val[i], i ^ n ? ' ' : '\n');
    }
    puts("=======");
  }
  inline void mdy(int x, int v) { val[find(x)] += v; }
  inline long long qry(int x) {
    find(x);
    return x == f[x] ? val[x] : val[x] + val[f[x]];
  }
} T1;
struct Tree2 {
  int f[N << 1], val[N << 1];
  inline void init() {
    for (int i = 1; i <= n + m; i++) f[i] = i, val[i] = 0;
  }
  inline int find(int x) {
    if (x == f[x]) return x;
    int p = find(f[x]);
    if (p ^ f[x]) {
      val[x] = max(val[x], val[f[x]]);
      f[x] = p;
    }
    return p;
  }
  inline void merge(int u, int v) {
    if ((u = find(u)) == (v = find(v))) return;
    f[u] = v;
  }
  inline void mdy(int x, int v) { val[find(x)] = v; }
  inline int qry(int x) {
    find(x);
    return x == f[x] ? val[x] : max(val[x], val[f[x]]);
  }
} T2;
struct node {
  int id, v, x;
  inline node(int _id = 0, int _v = 0, int _x = 0) {
    id = _id;
    v = _v;
    x = _x;
  }
};
vector<node> v[N];
long long ans[N];
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) sz[i] = 1;
  T1.init();
  T2.init();
  for (int i = 1; i <= m; i++) {
    q[i].rd();
    if (q[i].opt[0] == 'M') {
      T2.merge(q[i].x, i + n);
      T2.merge(q[i].y, i + n);
    } else if (q[i].opt[0] == 'Z') {
      T2.mdy(q[i].x, i);
    } else if (q[i].opt[0] == 'Q') {
      int lst = T2.qry(q[i].x);
      v[lst].push_back(node(i, -1, q[i].x));
      v[i].push_back(node(i, 1, q[i].x));
    }
  }
  for (int i = 1; i <= m; i++) {
    switch (q[i].opt[0]) {
      case 'U': {
        T1.merge(q[i].x, i + n);
        T1.merge(q[i].y, i + n);
        sz[q[i].x] += sz[q[i].y];
        break;
      }
      case 'A': {
        T1.mdy(q[i].x, sz[q[i].x]);
        break;
      }
    }
    for (auto cur : v[i]) ans[cur.id] += cur.v * T1.qry(cur.x);
  }
  for (int i = 1; i <= m; i++)
    if (q[i].opt[0] == 'Q') printf("%lld\n", ans[i]);
  return 0;
}
