#include <bits/stdc++.h>
#pragma gcc optimize("O3")
#pragma gcc optimize("Ofast")
#pragma gcc optimize("unroll-loops")
using namespace std;
const int INF = 1e9;
const int TMX = 1 << 18;
const long long llINF = 1e18;
const long long mod = 11092019;
const long long hashmod = 100003;
const int MAXN = 20000;
const int MAXM = 4000000;
int n, m, Q, k, cnt[500005], cnt2[500005], dep[100005], p[100005];
int ti[500005], sti[500005], eti[500005], LL[500005];
int vis[100005], sz[100005];
int q[500005];
vector<int> ans;
vector<pair<int, int>> t[2000005];
stack<pair<pair<int, int>, pair<int, int>>> st;
struct LifeS {
  int first, second, s, e;
};
vector<LifeS> life;
int Find(int first) {
  if (p[first] == first) return first;
  return Find(p[first]);
}
int merge(int first, int second) {
  first = Find(first), second = Find(second);
  if (first == second) return 0;
  if (dep[first] < dep[second]) swap(first, second);
  p[second] = first;
  sz[first] += sz[second];
  if (dep[first] == dep[second]) {
    dep[first]++;
    st.push({{first, second}, {1, sz[second]}});
  } else
    st.push({{first, second}, {0, sz[second]}});
  return 1;
}
void add(int node, int l, int r, int rl, int rr, pair<int, int> first) {
  if (l > rr || rl > r) return;
  if (rl <= l && r <= rr) {
    t[node].push_back(first);
    return;
  }
  int mid = (l + r) >> 1;
  add(node * 2, l, mid, rl, rr, first),
      add(node * 2 + 1, mid + 1, r, rl, rr, first);
}
void Rollback(int cntt) {
  for (int i = 1; i <= cntt; i++) {
    auto j = st.top();
    st.pop();
    sz[j.first.first] -= j.second.second;
    p[j.first.second] = j.first.second;
    if (j.second.first) dep[j.first.first]--;
  }
}
void query(int node, int l, int r) {
  int cntt = 0;
  for (auto i : t[node]) cntt += merge(i.first, i.second);
  if (l == r) {
    cout << sz[Find(q[l])] << '\n';
    Rollback(cntt);
    return;
  }
  int mid = (l + r) >> 1;
  query(node * 2, l, mid);
  query(node * 2 + 1, mid + 1, r);
  Rollback(cntt);
}
struct qqq {
  int first, second, s, e;
};
vector<qqq> qq;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> Q >> k;
  for (int i = 1; i <= n; i++) p[i] = i, sz[i] = 1, dep[i] = 0;
  cnt[0] = 1;
  for (int i = 1; i <= Q; i++) {
    int op, first, second;
    cin >> op;
    if (op == 1) {
      cin >> first >> second;
      if (first > second) swap(first, second);
      qq.push_back({first, second, i, cnt[i - 1] + k - 1});
    } else if (op == 2) {
      eti[cnt[i - 1]] = cnt2[i - 1] + 1;
      cin >> first, cnt2[i] = 1, ti[cnt2[i - 1] + 1] = cnt[i - 1],
                    q[cnt2[i - 1] + 1] = first;
    } else
      LL[cnt[i - 1] + 1] = i, cnt[i] = 1;
    cnt[i] += cnt[i - 1];
    cnt2[i] += cnt2[i - 1];
    eti[cnt[i]] = max(eti[cnt[i]], eti[cnt[i - 1]]);
  }
  for (qqq i : qq) {
    if (i.e > cnt[Q]) i.e = cnt[Q];
    add(1, 1, cnt2[Q], cnt2[i.s] + 1, eti[i.e], {i.first, i.second});
  }
  query(1, 1, cnt2[Q]);
}
