#include <bits/stdc++.h>
using namespace std;
struct UF {
  vector<int> belong;
  vector<int> size;
  void resize(int n) {
    belong.assign(n + 1, -1);
    size.assign(n + 1, 1);
  }
  inline int root(int b) {
    if (belong[b] == -1) {
      return b;
    }
    belong[b] = root(belong[b]);
    return belong[b];
  }
  void merge(int a, int b) {
    a = root(a);
    b = root(b);
    if (a == b) return;
    belong[b] = a;
    size[a] += size[b];
  }
};
UF uf;
int n;
int m;
char buf[3];
struct st {
  char ty;
  int a, b;
};
vector<st> v;
vector<int> vu;
vector<int> vm;
bool use[500002];
vector<int> g[500002];
inline void dfs(int b, vector<int> &ord) {
  use[b] = true;
  ord.push_back(b);
  for (int i = 0; i < g[b].size(); i++) {
    int go = g[b][i];
    if (use[go] == false) {
      dfs(go, ord);
    }
  }
}
void precalc(char s, vector<int> &ord) {
  memset(use, false, sizeof(use));
  uf.resize(n);
  for (int i = 0; i < n; i++) {
    g[i].clear();
  }
  for (int i = 0; i < v.size(); i++) {
    if (v[i].ty == s) {
      g[v[i].a].push_back(v[i].b);
      uf.merge(v[i].a, v[i].b);
    }
  }
  for (int i = 0; i < n; i++) {
    int r = uf.root(i);
    if (use[r] == false) dfs(r, ord);
  }
}
struct max_seg {
  int seg[500002 * 4];
  int lazy[500002 * 4];
  max_seg() {
    memset(seg, -1, sizeof(seg));
    memset(lazy, -1, sizeof(lazy));
  }
  void update(int b) {
    if (b * 2 + 2 < 500002 * 4) {
      lazy[b * 2 + 1] = max(lazy[b * 2 + 1], lazy[b]);
      lazy[b * 2 + 2] = max(lazy[b * 2 + 2], lazy[b]);
    }
    seg[b] = max(seg[b], lazy[b]);
    lazy[b] = -1;
  }
  inline void add(int b, int l, int r, int ll, int rr, int x) {
    update(b);
    if (rr <= l || r <= ll) {
      return;
    }
    if (ll <= l && r <= rr) {
      lazy[b] = max(lazy[b], x);
      update(b);
      return;
    }
    add(b * 2 + 1, l, (l + r) >> 1, ll, rr, x);
    add(b * 2 + 2, (l + r) >> 1, r, ll, rr, x);
    seg[b] = max(seg[b * 2 + 1], seg[b * 2 + 2]);
  }
  inline int query(int b, int l, int r, int ll) {
    update(b);
    if (r <= ll || ll < l) return -1;
    if (l + 1 == r) {
      return seg[b];
    }
    return max(query(b * 2 + 1, l, (l + r) >> 1, ll),
               query(b * 2 + 2, (l + r) >> 1, r, ll));
  }
};
struct add_seg {
  long long int seg[500002 * 4];
  long long int lazy[500002 * 4];
  add_seg() {
    memset(seg, 0, sizeof(seg));
    memset(lazy, 0, sizeof(lazy));
  }
  void update(int b) {
    if (b * 2 + 2 < 500002 * 4) {
      lazy[b * 2 + 1] += lazy[b];
      lazy[b * 2 + 2] += lazy[b];
    }
    seg[b] += lazy[b];
    lazy[b] = 0;
  }
  inline void add(int b, int l, int r, int ll, int rr, int x) {
    update(b);
    if (rr <= l || r <= ll) {
      return;
    }
    if (ll <= l && r <= rr) {
      lazy[b] += x;
      update(b);
      return;
    }
    add(b * 2 + 1, l, (l + r) >> 1, ll, rr, x);
    add(b * 2 + 2, (l + r) >> 1, r, ll, rr, x);
    seg[b] = seg[b * 2 + 1] + seg[b * 2 + 2];
  }
  inline long long int query(int b, int l, int r, int ll) {
    update(b);
    if (r <= ll || ll < l) return 0;
    if (l + 1 == r) {
      return seg[b];
    }
    return query(b * 2 + 1, l, (l + r) >> 1, ll) +
           query(b * 2 + 2, (l + r) >> 1, r, ll);
  }
};
max_seg seg1;
add_seg seg2;
int lef[500002];
int rig[500002];
long long int ans[500002];
vector<pair<int, int> > ev[500002];
int main() {
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    scanf("%s", buf);
    int a, b;
    scanf("%d", &a);
    if (buf[0] == 'U' || buf[0] == 'M') {
      scanf("%d", &b);
      a--;
      b--;
      v.push_back({buf[0], a, b});
    } else {
      a--;
      v.push_back({buf[0], a, -1});
    }
  }
  precalc('U', vu);
  precalc('M', vm);
  for (int i = 0; i < vm.size(); i++) {
    lef[vm[i]] = rig[vm[i]] = i;
  }
  for (int i = 0; i < v.size(); i++) {
    if (v[i].ty == 'M') {
      int a = v[i].a;
      int b = v[i].b;
      if (rig[a] > rig[b]) puts("e");
      if (rig[a] + 1 != lef[b]) puts("e");
      rig[a] = rig[b];
      continue;
    }
    if (v[i].ty == 'Z') {
      int id = v[i].a;
      seg1.add(0, 0, n, lef[id], rig[id] + 1, i);
      continue;
    }
    if (v[i].ty == 'Q') {
      int id = v[i].a;
      int f = seg1.query(0, 0, n, lef[id]);
      if (f >= 0) ev[f].push_back(make_pair(id, i));
    }
  }
  for (int i = 0; i < vu.size(); i++) {
    lef[vu[i]] = rig[vu[i]] = i;
  }
  for (int i = 0; i < v.size(); i++) {
    if (v[i].ty == 'U') {
      int a = v[i].a;
      int b = v[i].b;
      if (rig[a] > rig[b]) puts("e");
      if (rig[a] + 1 != lef[b]) puts("e");
      rig[a] = rig[b];
      continue;
    }
    if (v[i].ty == 'A') {
      int id = v[i].a;
      seg2.add(0, 0, n, lef[id], rig[id] + 1, rig[id] - lef[id] + 1);
      continue;
    }
    if (v[i].ty == 'Q') {
      int id = v[i].a;
      ans[i] += seg2.query(0, 0, n, lef[id]);
      printf("%lld\n", ans[i]);
      continue;
    }
    for (int j = 0; j < ev[i].size(); j++) {
      int id = ev[i][j].second;
      ans[id] -= seg2.query(0, 0, n, lef[ev[i][j].first]);
    }
  }
  return 0;
}
