#include <bits/stdc++.h>
using namespace std;
inline int gi() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = (x << 3) + (x << 1) + (ch ^ 48);
    ch = getchar();
  }
  return (f == 1) ? x : -x;
}
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
const int maxn = 6e5 + 5;
int n, q, k;
int val[maxn], fa[maxn], son[maxn][2], maxv[maxn], root[maxn], tot, siz[maxn],
    t, si[maxn], temp[maxn];
bool rev[maxn];
inline bool nroot(int u) { return son[fa[u]][0] == u || son[fa[u]][1] == u; }
inline void pushup(int u) {
  if (val[maxv[son[u][0]]] < val[maxv[son[u][1]]] &&
      val[maxv[son[u][0]]] < val[u])
    maxv[u] = maxv[son[u][0]];
  else if (val[maxv[son[u][1]]] < val[u])
    maxv[u] = maxv[son[u][1]];
  else
    maxv[u] = u;
  siz[u] = siz[son[u][0]] + siz[son[u][1]] + si[u] + temp[u];
}
inline void pushdown(int u) {
  if (rev[u]) {
    swap(son[u][0], son[u][1]);
    rev[son[u][0]] ^= 1, rev[son[u][1]] ^= 1;
    rev[u] = 0;
  }
}
inline void pushall(int u) {
  if (nroot(u)) pushall(fa[u]);
  pushdown(u);
}
inline void rotate(int x) {
  int y = fa[x], z = fa[y], k = son[y][1] == x;
  if (nroot(y)) son[z][son[z][1] == y] = x;
  fa[x] = z;
  son[y][k] = son[x][k ^ 1];
  fa[son[x][k ^ 1]] = y;
  son[x][k ^ 1] = y;
  fa[y] = x;
  pushup(y);
  pushup(x);
}
inline void splay(int x) {
  pushall(x);
  while (nroot(x)) {
    int y = fa[x], z = fa[y];
    if (nroot(y)) {
      if ((son[z][1] == y) ^ (son[y][1] == x))
        rotate(x);
      else
        rotate(y);
    }
    rotate(x);
  }
}
inline void access(int x) {
  for (int y = 0; x; y = x, x = fa[x]) {
    splay(x);
    si[x] = si[x] + siz[son[x][1]] - siz[y];
    son[x][1] = y;
    pushup(x);
  }
}
inline int findroot(int x) {
  access(x);
  splay(x);
  pushdown(x);
  while (son[x][0]) x = son[x][0], pushdown(x);
  splay(x);
  return x;
}
inline void makeroot(int x) {
  access(x);
  splay(x);
  rev[x] ^= 1;
}
inline void link(int x, int y) {
  makeroot(x);
  access(y);
  splay(y);
  fa[x] = y;
  si[y] += siz[x];
  pushup(y);
}
inline void cut(int x, int y) {
  makeroot(x);
  access(y);
  splay(y);
  if (findroot(y) == x && fa[y] == x && !son[y][0]) {
    fa[y] = son[x][1] = 0;
    pushup(x);
  }
}
inline bool query(int x, int y) {
  makeroot(x);
  return findroot(y) == x;
}
inline void split(int x, int y) {
  makeroot(x);
  access(y);
  splay(y);
}
set<pair<int, int> > s[maxn];
vector<pair<int, int> > v;
int tim[maxn], curr;
int main() {
  memset(val, 0x3f, sizeof(val));
  n = gi(), q = gi(), k = gi();
  int now = 1, curr = 0;
  v.push_back(pair<int, int>(0, 0));
  for (int i = 1; i <= n; ++i) temp[i] = 1;
  for (int i = 1; i <= q; ++i) {
    int typ = gi();
    if (typ == 1) {
      int x = gi(), y = gi();
      if (x < y) swap(x, y);
      s[now].insert(pair<int, int>(x, y));
      ++tot;
      tim[tot] = now;
      v.push_back(pair<int, int>(x, y));
      if (query(x, y)) {
        split(x, y);
        int now1 = maxv[y] - n;
        s[maxv[y]].erase(pair<int, int>(v[now1].first, v[now1].second));
        cut(v[now1].first, now1 + n);
        cut(v[now1].second, now1 + n);
        link(x, tot + n);
        link(y, tot + n);
        val[tot + n] = now;
      } else {
        link(x, tot + n);
        link(tot + n, y);
        val[tot + n] = now;
      }
    } else if (typ == 2) {
      int x = gi();
      makeroot(x);
      printf("%d\n", siz[x]);
    } else {
      now++;
      if (now - k >= 1) {
        int now1 = now - k;
        while (tim[curr + 1] == now1) {
          curr++;
          if (s[now1].count(v[curr])) s[now1].erase(v[curr]);
          cut(v[curr].first, curr + n);
          cut(v[curr].second, curr + n);
        }
      }
    }
  }
  return 0;
}
