#include <bits/stdc++.h>   using namespace std;   template <class T>   inline void rd(T &x) {     x = 0;     char c = getchar();     int f = 1;     while (!isdigit(c)) {       if (c ==  - ) f = -1;       c = getchar();     }     while (isdigit(c)) x = x * 10 -  0  + c, c = getchar();     x *= f;   }   template <class T>   inline void cmax(T &x, T y) {     if (x < y) x = y;   }   template <class T>   inline void cmin(T &x, T y) {     if (y < x) x = y;   }   const int N = 5e5 + 10, M = N << 1;   int n, m;   struct Tree {     int F[M], fa[M], ch[M][2], ti[M], sz[M], ncnt;     int dfn[M], lb[M], rb[M], id;     void init() {       ncnt = n;       for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1;     }     int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }     void un(int x, int y, int t) {       int fx = find(x), fy = find(y), u = ++ncnt;       fa[u] = fa[fx] = fa[fy] = u, ti[u] = t, sz[u] = sz[fx] + sz[fy];       ch[u][0] = fx, ch[u][1] = fy;     }     void dfs(int u) {       if (!ch[u][0]) {         lb[u] = rb[u] = dfn[u] = ++id;       } else {         lb[u] = id + 1;         dfs(ch[u][0]), dfs(ch[u][1]);         F[ch[u][0]] = F[ch[u][1]] = u;         rb[u] = id;       }     }     void build() {       for (int i = 1; i <= ncnt; ++i)         if (find(i) == i) dfs(i);       for (int i = 1; i <= n; ++i) fa[i] = i;     }     int get(int x, int t) {       while (F[fa[x]] && ti[F[fa[x]]] <= t) fa[x] = F[fa[x]];       return fa[x];     }   } A, B;   namespace seg {   int cov[N << 2];   inline void push_down(int c) {     if (cov[c]) {       cmax(cov[c << 1], cov[c]);       cmax(cov[c << 1 | 1], cov[c]);       cov[c] = 0;     }   }   void upd(int l, int r, int c, int L, int R, int v) {     if (L <= l && R >= r) return (void)(cov[c] = v);     int mid = l + r >> 1;     push_down(c);     if (L <= mid) upd(l, mid, c << 1, L, R, v);     if (R > mid) upd(mid + 1, r, c << 1 | 1, L, R, v);   }   int query(int l, int r, int c, int v) {     if (l == r) return cov[c];     int mid = l + r >> 1;     push_down(c);     if (v <= mid)       return query(l, mid, c << 1, v);     else       return query(mid + 1, r, c << 1 | 1, v);   }   }  // namespace seg   namespace Bit {   long long c[N];   void add(int i, int t) {     for (; i <= n; i += i & -i) c[i] += t;   }   void add(int l, int r, int t) { add(l, t), add(r + 1, -t); }   long long query(int i) {     long long ans = 0;     for (; i; i -= i & -i) ans += c[i];     return ans;   }   }  // namespace Bit   struct OPT {     int ty, t, x;     OPT(int ty = 0, int t = 0, int x = 0) : ty(ty), t(t), x(x) {}   };   vector<OPT> Q;   long long ans[N];   struct Que {     int p, id, sgn;     Que(int p = 0, int id = 0, int sgn = 0) : p(p), id(id), sgn(sgn) {}   };   vector<Que> R[N];   char ty[20];   int main() {     rd(n), rd(m);     A.init(), B.init();     for (int i = 1, x, y; i <= m; ++i) {       scanf( %s , ty);       if (ty[0] ==  U ) {         rd(x), rd(y);         A.un(x, y, i);       } else if (ty[0] ==  M ) {         rd(x), rd(y);         B.un(x, y, i);       } else {         rd(x);         Q.push_back(OPT(ty[0] ==  A  ? 1 : (ty[0] ==  Z  ? 2 : 3), i, x));       }     }     A.build(), B.build();     int qtot = 0;     for (int i = 0; i < Q.size(); ++i)       if (Q[i].ty == 2) {         int x = B.get(Q[i].x, Q[i].t);         seg::upd(1, n, 1, B.lb[x], B.rb[x], Q[i].t);       } else if (Q[i].ty == 3) {         R[Q[i].t].push_back(Que(A.dfn[Q[i].x], ++qtot, 1));         int pre = seg::query(1, n, 1, B.dfn[Q[i].x]);         if (pre) R[pre].push_back(Que(A.dfn[Q[i].x], qtot, -1));       }     int q = 0;     for (int i = 1; i <= m; ++i) {       while (q < Q.size() && Q[q].t <= i) {         if (Q[q].ty == 1) {           int anc = A.get(Q[q].x, Q[q].t);           Bit::add(A.lb[anc], A.rb[anc], A.sz[anc]);         }         q++;       }       for (int j = 0; j < R[i].size(); ++j)         ans[R[i][j].id] += R[i][j].sgn * Bit::query(R[i][j].p);     }     for (int i = 1; i <= qtot; ++i) printf( %lld n , ans[i]);     return 0;   }