#include <bits/stdc++.h>
using namespace std;
int n, q, k, day = 1;
int qt[500002], qa[500002], qb[500002];
int par[500002], sz[500002];
int dayEnd[500002];
vector<int> lst[2000002];
stack<int> stk;
int find(int x) {
  if (par[x] == x) return x;
  return find(par[x]);
}
void merge(int x, int y) {
  x = find(x), y = find(y);
  if (x == y) return;
  if (sz[x] < sz[y]) swap(x, y);
  par[y] = x, sz[x] += sz[y];
  stk.push(y);
}
void cancel(int tSize) {
  while ((int)stk.size() > tSize) {
    int tmp = stk.top();
    stk.pop();
    sz[par[tmp]] -= sz[tmp];
    par[tmp] = tmp;
  }
}
void update(int i, int l, int r, int s, int e, int val) {
  if (r < s || e < l) return;
  if (s <= l && r <= e) {
    lst[i].push_back(val);
    return;
  }
  int m = (l + r) >> 1;
  update(i * 2, l, m, s, e, val);
  update(i * 2 + 1, m + 1, r, s, e, val);
  return;
}
void solve(int i, int l, int r) {
  int tSize = (int)stk.size();
  for (auto query : lst[i]) {
    merge(qa[query], qb[query]);
  }
  if (l == r) {
    if (qt[l] == 2) {
      printf("%d\n", sz[find(qa[l])]);
    }
  } else {
    int m = (l + r) >> 1;
    solve(i * 2, l, m), solve(i * 2 + 1, m + 1, r);
  }
  cancel(tSize);
}
int main() {
  scanf("%d %d %d", &n, &q, &k);
  for (int i = 1; i <= n; i++) sz[i] = 1, par[i] = i;
  for (int i = 1; i <= q; i++) {
    scanf("%d", &qt[i]);
    if (qt[i] <= 2)
      scanf("%d", &qa[i]);
    else
      dayEnd[day++] = i - 1;
    if (qt[i] == 1) scanf("%d", &qb[i]);
  }
  dayEnd[day] = q;
  int dayCnt = 1;
  for (int i = 1; i <= q; i++) {
    if (qt[i] == 1) update(1, 1, q, i, dayEnd[min(dayCnt + k - 1, day)], i);
    if (qt[i] == 3) dayCnt++;
  }
  solve(1, 1, q);
}
