#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 5;
vector<int> v[MAXN];
pair<int, int> mn[MAXN];
pair<int, int> edge[MAXN];
int n, fa[MAXN], ch[MAXN][2], st[MAXN], top, rev[MAXN];
int siz[MAXN], sizv[MAXN], sz[MAXN], val[MAXN], edge_cnt;
inline int read() {
  int x = 0;
  char ch = getchar();
  while (!isdigit(ch)) ch = getchar();
  while (isdigit(ch)) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x;
}
template <typename T>
inline void Min(T &x, T y) {
  if (x > y) x = y;
}
inline bool check(int x) { return ch[fa[x]][1] == x; }
inline bool isroot(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
inline void pushup(int x) {
  mn[x] = min(mn[ch[x][0]], mn[ch[x][1]]);
  Min(mn[x], make_pair(val[x], x));
  siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + sizv[x] + sz[x];
}
inline void pushrev(int x) {
  rev[x] ^= 1;
  swap(ch[x][0], ch[x][1]);
}
inline void pushdown(int x) {
  if (!rev[x]) return;
  pushrev(ch[x][0]);
  pushrev(ch[x][1]);
  rev[x] = 0;
}
inline void pushdw(int x) {
  st[++top] = x;
  while (!isroot(x)) st[++top] = x = fa[x];
  while (top) pushdown(st[top--]);
}
inline void rotate(int x) {
  int y = fa[x], z = fa[y];
  int k = check(x), w = ch[x][k ^ 1];
  if (!isroot(y)) ch[z][check(y)] = x;
  ch[x][k ^ 1] = y, fa[y] = x, fa[x] = z;
  ch[y][k] = w, fa[w] = y;
  pushup(y), pushup(x);
}
inline void splay(int x) {
  pushdw(x);
  for (int y; !isroot(x); rotate(x))
    if (!isroot(y = fa[x])) rotate(check(x) ^ check(y) ? x : y);
}
inline void access(int x) {
  for (int y = 0; x; y = x, x = fa[x])
    splay(x), sizv[x] += siz[ch[x][1]], sizv[x] -= siz[y], ch[x][1] = y,
                                                           pushup(x);
}
inline int findroot(int x) {
  access(x), splay(x);
  while (ch[x][0]) x = ch[x][0];
  return x;
}
inline void makeroot(int x) {
  access(x), splay(x);
  pushrev(x);
}
inline bool check(int x, int y) {
  makeroot(x);
  return findroot(y) == x;
}
inline void split(int x, int y) {
  makeroot(x);
  access(y);
  splay(y);
}
inline void link(int x, int y) {
  split(x, y);
  fa[x] = y, sizv[y] += siz[x], pushup(y);
}
inline void cut(int x, int y) {
  split(x, y);
  if (ch[y][0] != x || ch[x][1]) return;
  ch[y][0] = fa[x] = 0, pushup(y);
}
inline void link(int a) {
  int x = edge[a].first;
  int y = edge[a].second;
  if (!check(x, y))
    link(x, n + a), link(n + a, y);
  else {
    int cur = mn[y].second;
    assert(cur > n);
    cut(cur, edge[cur - n].first);
    cut(cur, edge[cur - n].second);
    link(x, n + a), link(n + a, y);
  }
}
inline int query(int x) {
  access(x), splay(x);
  return siz[x];
}
int main() {
  n = read();
  int t = read(), k = read(), T = 1;
  val[0] = 0x3f3f3f3f, mn[0] = make_pair(val[0], 0);
  for (int i = 1; i <= n; i++) sz[i] = 1, val[i] = 0x3f3f3f3f;
  while (t--) {
    int opt = read();
    if (opt == 1) {
      int x = read(), y = read();
      edge[++edge_cnt] = make_pair(x, y);
      v[T].push_back(edge_cnt);
      val[edge_cnt + n] = T, link(edge_cnt);
    } else if (opt == 2) {
      int x = read();
      printf("%d\n", query(x));
    } else {
      ++T;
      if (T - k > 0)
        for (auto x : v[T - k])
          cut(edge[x].first, x + n), cut(edge[x].second, x + n);
    }
  }
  return 0;
}
