#include <bits/stdc++.h>
using namespace std;
const int N = 100321;
int dsuP[N], dsuS[N];
vector<pair<int *, int>> hist;
int dsuRoot(int v) {
  while (dsuP[v] != -1) v = dsuP[v];
  return v;
}
void dsuMerge(int a, int b) {
  a = dsuRoot(a);
  b = dsuRoot(b);
  if (a == b) return;
  if (dsuS[a] >= dsuS[b]) {
    hist.emplace_back(&dsuP[b], dsuP[b]);
    hist.emplace_back(&dsuS[a], dsuS[a]);
    dsuP[b] = a;
    dsuS[a] += dsuS[b];
  } else {
    hist.emplace_back(&dsuP[a], dsuP[a]);
    hist.emplace_back(&dsuS[b], dsuS[b]);
    dsuP[a] = b;
    dsuS[b] += dsuS[a];
  }
}
struct Query {
  int t, u, v;
  int answer;
};
int n, m, k;
Query q[5 * N];
vector<pair<int, int>> t[N * 20];
void addEdge(int l, int r, pair<int, int> uv, int c, int cl, int cr) {
  if (l > cr || r < cl) return;
  if (l <= cl && cr <= r) {
    t[c].push_back(uv);
    return;
  }
  int mid = (cl + cr) / 2;
  addEdge(l, r, uv, c * 2 + 1, cl, mid);
  addEdge(l, r, uv, c * 2 + 2, mid + 1, cr);
}
void go(int c, int cl, int cr) {
  int startSize = hist.size();
  for (pair<int, int> uv : t[c]) dsuMerge(uv.first, uv.second);
  if (cl == cr) {
    if (q[cl].t == 2) q[cl].answer = (dsuS[dsuRoot(q[cl].u)]);
  } else {
    int mid = (cl + cr) / 2;
    go(c * 2 + 1, cl, mid);
    go(c * 2 + 2, mid + 1, cr);
  }
  while ((int)hist.size() > startSize) {
    *hist.back().first = hist.back().second;
    hist.pop_back();
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin >> n >> m >> k;
  for (int i = 0; i < n; ++i) dsuP[i] = -1, dsuS[i] = 1;
  deque<vector<pair<int, int>>> edges_in_day(1);
  set<pair<pair<int, int>, int>> edges;
  for (int i = 0; i < m; ++i) {
    cin >> q[i].t;
    if (q[i].t == 1) {
      cin >> q[i].u >> q[i].v;
      q[i].u--, q[i].v--;
    } else if (q[i].t == 2) {
      cin >> q[i].u;
      q[i].u--;
      q[i].v = 1e9;
    }
    if (q[i].u > q[i].v) swap(q[i].u, q[i].v);
    if (q[i].t == 1)
      edges.emplace(pair<int, int>(q[i].u, q[i].v), i),
          edges_in_day.back().emplace_back(q[i].u, q[i].v);
    else if (q[i].t == 3) {
      if (edges_in_day.size() >= k) {
        for (const auto &[u, v] : edges_in_day.front()) {
          auto iter = edges.lower_bound(make_pair(pair<int, int>(u, v), 0));
          addEdge(iter->second, i, iter->first, 0, 0, m - 1);
          edges.erase(iter);
        }
        edges_in_day.pop_front();
      }
      edges_in_day.emplace_back();
    }
  }
  for (auto e : edges) addEdge(e.second, m - 1, e.first, 0, 0, m - 1);
  go(0, 0, m - 1);
  for (int i = 0; i < m; ++i)
    if (q[i].t == 2) {
      cout << q[i].answer << '\n';
    }
  return 0;
}
