#include <bits/stdc++.h>
using namespace std;
template <typename tp>
inline void read(tp& x) {
  x = 0;
  char tmp;
  bool key = 0;
  for (tmp = getchar(); !isdigit(tmp); tmp = getchar()) key = (tmp == '-');
  for (; isdigit(tmp); tmp = getchar()) x = (x << 3) + (x << 1) + (tmp ^ '0');
  if (key) x = -x;
}
template <typename tp>
inline void ckmn(tp& x, tp y) {
  x = x < y ? x : y;
}
template <typename tp>
inline void ckmx(tp& x, tp y) {
  x = x < y ? y : x;
}
const int N = 500010;
int n, m;
vector<pair<long long, int> > vec[N];
int las[N], rec[N], tms[N];
struct tree {
  int uni[N], fa[N], sz[N];
  int getfa(int pos) {
    return pos == uni[pos] ? pos : uni[pos] = getfa(uni[pos]);
  }
  int checklas(int pos) {
    int ret = 0, cur = 0;
    for (; pos; cur = tms[pos], pos = fa[pos])
      if (las[pos] > cur) ret = max(ret, las[pos]);
    return ret;
  }
  long long query(int pos, int lim) {
    long long ret = 0;
    int cur = 0;
    for (; pos; cur = rec[pos], pos = fa[pos]) {
      if ((int)vec[pos].size() == cur) continue;
      if (vec[pos].back().second <= lim) continue;
      if (vec[pos][cur].second > lim) {
        ret += vec[pos].back().first;
        if (cur > 0) ret -= vec[pos][cur - 1].first;
        continue;
      }
      int p = lower_bound(vec[pos].begin(), vec[pos].end(),
                          max(lim, vec[pos][cur].second),
                          [=](pair<long long, int> a, int b) -> bool {
                            return a.second < b;
                          }) -
              vec[pos].begin() - 1;
      ret += vec[pos].back().first - vec[pos][p].first;
    }
    return ret;
  }
  void init() {
    for (int i = (1); i <= (n); ++i) uni[i] = i, fa[i] = 0, sz[i] = 1;
  }
  void merge(int x, int y, int tp) {
    x = getfa(x), y = getfa(y);
    assert(x != y);
    if (sz[x] > sz[y]) swap(x, y);
    fa[x] = y;
    uni[x] = y;
    sz[y] += sz[x];
    if (tp == 0)
      rec[x] = (int)vec[y].size();
    else
      tms[x] = tp;
  }
} t[2];
int main() {
  char tp[3];
  int x, y;
  read(n), read(m);
  t[0].init();
  t[1].init();
  for (int i = (1); i <= (m); ++i) {
    scanf("%s", tp);
    if (*tp == 'U') {
      read(x), read(y);
      t[0].merge(x, y, 0);
    }
    if (*tp == 'M') {
      read(x), read(y);
      t[1].merge(x, y, i);
    }
    if (*tp == 'A') {
      read(x);
      x = t[0].getfa(x);
      if (!vec[x].empty())
        vec[x].push_back(
            pair<long long, int>(t[0].sz[x] + vec[x].back().first, i));
      else
        vec[x].push_back(pair<long long, int>(t[0].sz[x], i));
    }
    if (*tp == 'Z') {
      read(x);
      x = t[1].getfa(x);
      las[x] = i;
    }
    if (*tp == 'Q') {
      read(x);
      int tmp = t[1].checklas(x);
      cout << t[0].query(x, tmp) << endl;
    }
  }
  return 0;
}
