#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
const int Q = 5e5 + 100;
int n, q, k;
struct node {
  int u, v, tt;
} e[Q];
struct dsu {
  int nn, fa[Q], siz[Q];
  stack<pair<int, int> > s;
  void init(int _n) {
    nn = _n;
    for (int i = 0; i <= _n + 5; i++) fa[i] = i, siz[i] = 1;
  }
  int get(int x) {
    while (x != fa[x]) {
      x = fa[x];
    }
    return x;
  }
  bool merge(int x, int y) {
    int fx = get(x), fy = get(y);
    if (fx == fy) return false;
    if (siz[fx] > siz[fy]) swap(fx, fy), swap(x, y);
    fa[fx] = fy;
    siz[fy] += siz[fx];
    s.push(make_pair(fx, fy));
    return true;
  }
  void undo() {
    pair<int, int> now = s.top();
    s.pop();
    siz[now.second] -= siz[now.first];
    fa[now.first] = now.first;
  }
} DS;
int qt[Q], qv[Q];
vector<int> lase[Q];
vector<int> T[Q << 2];
void update(int id, int l, int r, int L, int R, int ii) {
  if (L <= l && R >= r) {
    T[id].push_back(ii);
    return;
  }
  int mid = l + r >> 1;
  if (L <= mid) update(id << 1, l, mid, L, R, ii);
  if (R > mid) update(id << 1 | 1, mid + 1, r, L, R, ii);
}
void query(int id, int l, int r) {
  int ct = 0;
  for (auto g : T[id]) ct += DS.merge(e[g].u, e[g].v);
  if (l == r) {
    if (qt[l]) {
      int ff = DS.get(qv[l]);
      printf("%d\n", DS.siz[ff]);
    }
    for (int i = 0; i < ct; i++) DS.undo();
    return;
  }
  int mid = l + r >> 1;
  query(id << 1, l, mid);
  query(id << 1 | 1, mid + 1, r);
  for (int i = 0; i < ct; i++) DS.undo();
}
int main() {
  scanf("%d%d%d", &n, &q, &k);
  DS.init(n + 1);
  int d = 1, eid = 0, tid = 0;
  for (int i = 1; i <= q; i++) {
    int op, x, y;
    scanf("%d", &op);
    tid++;
    if (op == 1) {
      eid++;
      scanf("%d%d", &e[eid].u, &e[eid].v);
      e[eid].tt = tid;
      lase[d].push_back(eid);
    } else if (op == 2) {
      scanf("%d", &x);
      qt[tid] = 1;
      qv[tid] = x;
    } else {
      d++;
      if (d > k) {
        int nowd = d - k;
        for (auto v : lase[nowd]) {
          update(1, 1, q, e[v].tt, tid, v);
        }
      }
    }
  }
  for (int i = d - k + 1; i <= d; i++) {
    for (auto v : lase[i]) {
      update(1, 1, q, e[v].tt, q, v);
    }
  }
  query(1, 1, q);
  return 0;
}
