#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int Q = 5e5 + 10;
struct USF {
  int fa[N], rk[N], sz[N], top;
  struct Stack {
    int u, v, rk, sz;
  } sta[N];
  inline void init(int n) {
    top = 0;
    for (int i = 1; i <= n; i++) fa[i] = i, sz[i] = 1;
  }
  inline int find(int x) { return x == fa[x] ? x : find(fa[x]); }
  inline bool merge(int u, int v) {
    int fu = find(u), fv = find(v);
    if (fu == fv) return false;
    if (rk[fu] > rk[fv]) swap(u, v), swap(fu, fv);
    sta[++top] = {fu, fv, rk[fv], sz[fv]};
    fa[fu] = fv, rk[fv] += (rk[fu] == rk[fv]), sz[fv] += sz[fu];
    return true;
  }
  inline bool is_connected(int u, int v) {
    int fu = find(u), fv = find(v);
    if (fu == fv) return true;
    return false;
  }
  inline void undo(int k) {
    while (k--) {
      Stack &now = sta[top--];
      int u = now.u, v = now.v;
      fa[u] = u, rk[v] = now.rk, sz[v] = now.sz;
    }
  }
  inline int query(int u) {
    int fu = find(u);
    return sz[fu];
  }
} usf;
struct Node {
  int x = 0, y = 0, op = 0;
  Node() {}
  Node(int _x, int _y, int _op) : x(_x), y(_y), op(_op) {}
};
struct Tree {
  int l, r;
  vector<Node> val;
} tree[Q << 2];
void build(int pos, int l, int r) {
  tree[pos] = {l, r, vector<Node>()};
  if (l == r) return;
  int mid = l + r >> 1;
  build(pos << 1, l, mid);
  build(pos << 1 | 1, mid + 1, r);
}
void update(int pos, int l, int r, Node &q) {
  if (l <= tree[pos].l && tree[pos].r <= r) {
    tree[pos].val.push_back(q);
    return;
  }
  int mid = tree[pos].l + tree[pos].r >> 1;
  if (l <= mid) update(pos << 1, l, r, q);
  if (mid < r) update(pos << 1 | 1, l, r, q);
}
void solve(int pos, vector<int> &ans) {
  int now = usf.top;
  for (auto it : tree[pos].val)
    if (it.op == 1) usf.merge(it.x, it.y);
  for (auto it : tree[pos].val)
    if (it.op == 2) ans[tree[pos].l] = usf.query(it.x);
  if (tree[pos].l != tree[pos].r) {
    solve(pos << 1, ans);
    solve(pos << 1 | 1, ans);
  }
  usf.undo(usf.top - now);
}
int main() {
  int n, q, k;
  scanf("%d %d %d", &n, &q, &k);
  usf.init(n);
  vector<int> days(1, 0);
  vector<Node> v(q + 1);
  for (int i = 1; i <= q; i++) {
    int op;
    scanf("%d", &op);
    if (op == 1) {
      int x, y;
      scanf("%d %d", &x, &y);
      v[i] = (Node){x, y, op};
    } else if (op == 2) {
      int x;
      scanf("%d", &x);
      v[i] = (Node){x, 0, op};
    } else
      days.push_back(i);
  }
  days.push_back(q + 1);
  build(1, 1, q + 1);
  int cur_day = 0, sz = (int)days.size();
  for (int i = 1; i <= q; i++) {
    if (v[i].x == 0)
      cur_day++;
    else if (v[i].y) {
      int rbor = (cur_day + k < sz ? days[cur_day + k] : q + 1);
      update(1, i, rbor, v[i]);
    } else
      update(1, i, i, v[i]);
  }
  vector<int> ans(q + 2, -1);
  solve(1, ans);
  for (int i = 1; i <= q; i++)
    if (ans[i] != -1) printf("%d\n", ans[i]);
  return 0;
}
