#include <bits/stdc++.h>
#pragma GCC optimize("O3", "Ofast", "unroll-loops", "omit-frame-pointer", \
                     "inline")
#pragma GCC option("arch=native", "tune=native", "no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
struct DSU_WITH_ROLLBACKS {
  struct dsu_save {
    long long u, urank, v, vrank, comps;
    bool bipart;
  };
  stack<dsu_save> op;
  vector<long long> rnk;
  vector<bool> col;
  bool bipartite;
  long long comps;
  DSU_WITH_ROLLBACKS() {}
  DSU_WITH_ROLLBACKS(long long N) { init(N); }
  void init(long long N) {
    rnk.clear();
    col.clear();
    while (!op.empty()) op.pop();
    rnk.resize(N);
    col.resize(N);
    for (long long i = 0; i < N; i++) {
      rnk[i] = 1;
      col[i] = false;
    }
    bipartite = true;
    comps = N;
  }
  pair<long long, bool> find(long long x) {
    if (rnk[x] > 0) return {x, col[x]};
    pair<long long, bool> tp = find(-rnk[x]);
    tp.second ^= col[x];
    return tp;
  }
  void join(long long a, long long b) {
    pair<long long, bool> ta = find(a), tb = find(b);
    a = ta.first;
    b = tb.first;
    op.push({a, rnk[a], b, rnk[b], comps, bipartite});
    if (a == b) {
      if (ta.second == tb.second) bipartite = false;
      return;
    }
    comps--;
    if (rnk[a] < rnk[b]) swap(a, b);
    rnk[a] += rnk[b];
    rnk[b] = -a;
    col[b] = col[b] ^ (ta.second == tb.second);
  }
  void rollback() {
    if (op.empty()) return;
    dsu_save x = op.top();
    op.pop();
    comps = x.comps;
    bipartite = x.bipart;
    rnk[x.u] = x.urank;
    col[x.u] = false;
    rnk[x.v] = x.vrank;
    col[x.v] = false;
  }
};
const long long MAXN = 5e5 + 100;
vector<long long> arr[MAXN];
vector<long long> res;
template <typename T, typename F, typename D>
struct ROLLBACK_TRICK {
  vector<vector<T>> ST;
  long long N;
  void add_to_tree(long long nodo, long long l, long long r, long long a,
                   long long b, T qu) {
    if (r < a || l > b) return;
    if (a <= l && r <= b) {
      ST[nodo].push_back(qu);
      return;
    }
    long long mid = (l + r) / 2;
    add_to_tree(nodo * 2, l, mid, a, b, qu);
    add_to_tree(nodo * 2 + 1, mid + 1, r, a, b, qu);
  }
  void add_query(T qu, long long l, long long r) {
    add_to_tree(1, 0, N - 1, l, r, qu);
  }
  void dfs(long long nodo, long long l, long long r, D &DS) {
    for (auto x : ST[nodo]) DS.join(x.first, x.second);
    if (l == r) {
      for (auto x : arr[l]) {
        res.push_back(DS.rnk[DS.find(x).first]);
      }
    } else {
      long long mid = (l + r) / 2;
      dfs(nodo * 2, l, mid, DS);
      dfs(nodo * 2 + 1, mid + 1, r, DS);
    }
    for (long long i = 0; i < ST[nodo].size(); i++) DS.rollback();
  }
  void solve(long long tn, vector<T> vect,
             vector<pair<long long, long long>> querys, D &DS) {
    assert(vect.size() == querys.size());
    N = tn;
    ST.clear();
    ST.resize(4 * (N + 4));
    for (long long i = 0; i < vect.size(); i++) {
      add_query(vect[i], querys[i].first, querys[i].second);
    }
    dfs(1, 0, N - 1, DS);
  }
};
int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  long long N, Q, K;
  cin >> N >> Q >> K;
  DSU_WITH_ROLLBACKS DSU(N + 1);
  vector<pair<long long, long long>> qu;
  vector<pair<long long, long long>> vect;
  deque<vector<pair<pair<long long, long long>, long long>>> D;
  vector<pair<pair<long long, long long>, long long>> temp;
  long long cont = 0;
  for (long long i = 1; i <= Q; i++) {
    long long tp;
    cin >> tp;
    if (tp == 1) {
      long long a, b;
      cin >> a >> b;
      temp.push_back({{a, b}, cont});
    }
    if (tp == 2) {
      long long q;
      cin >> q;
      arr[cont].push_back(q);
      cont++;
    }
    if (tp == 3) {
      D.push_back(temp);
      temp.clear();
      if (D.size() == K) {
        for (auto x : D.front()) {
          qu.push_back({x.second, cont});
          vect.push_back({x.first.first, x.first.second});
        }
        D.pop_front();
      }
      cont++;
    }
  }
  D.push_back(temp);
  while (D.size()) {
    for (auto x : D.front()) {
      qu.push_back({x.second, cont});
      vect.push_back({x.first.first, x.first.second});
    }
    D.pop_front();
  }
  cont++;
  ROLLBACK_TRICK<pair<long long, long long>, long long, DSU_WITH_ROLLBACKS> RT;
  RT.solve(cont, vect, qu, DSU);
  for (auto x : res) {
    cout << x << '\n';
  }
  return 0;
}
