/**
* @file cco24p6-1.cpp
* @author n685
* @brief
* @date 2024-06-14
*
*
*/
#ifndef LOCAL
// https://nor-blog.codeberg.page/posts/2021-10-26-gcc-optimization-pragmas/
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("bmi,bmi2,lzcnt,popcnt")
#endif
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// using namespace __gnu_pbds;
// const auto RANDOM =
// std::chrono::high_resolution_clock::now().time_since_epoch().count();
// struct chash {
// auto operator()(std::integral auto x) const { return x ^ RANDOM; }
// };
// template <std::integral T> using std::set = gp_hash_table<T, null_type,
// chash>;
#ifdef LOCAL
#include "dd/debug.h"
#else
#define dbg(...) 42
#define dbgR(...) 4242
#define dbgP(...) 420
#define dbgRP(...) 420420
void nline() {}
#endif
struct Node {
int node, par;
std::set<int>::iterator it;
};
auto main() -> int {
// #ifndef LOCAL
std::cin.tie(nullptr)->sync_with_stdio(false);
// #endif
int e;
std::cin >> e;
int n, q;
std::cin >> n >> q;
std::vector<std::set<int>> adj(n);
int64_t last = 0;
std::vector<std::set<int> *> cc(n);
for (int i = 0; i < n; ++i) {
cc[i] = new std::set<int>();
cc[i]->insert(i);
}
// int64_t join = 0, br = 0;
std::vector<int64_t> join{0}, br{0};
auto add = [&](int u, int v) -> void {
if (cc[u]->size() < cc[v]->size()) {
std::swap(u, v);
}
join.push_back(join.back() + static_cast<int64_t>(cc[u]->size()) *
static_cast<int64_t>(cc[v]->size()));
std::set<int> *s = cc[v];
for (int i : *s) {
cc[u]->insert(i);
cc[i] = cc[u];
}
delete s;
adj[u].insert(v);
adj[v].insert(u);
};
auto rem = [&](int u, int v) -> void {
adj[u].erase(v);
adj[v].erase(u);
std::array<std::queue<Node>, 2> q;
std::array<std::set<int>, 2> s{};
std::array<int, 2> cnt{};
s[0].insert(u);
s[1].insert(v);
if (!adj[u].empty()) {
q[0].emplace(u, -1, adj[u].begin());
}
if (!adj[v].empty()) {
q[1].emplace(v, -1, adj[v].begin());
}
for (int fl; !q[0].empty() && !q[1].empty();) {
if (s[1].size() < s[0].size()) {
fl = 1;
} else {
fl = 0;
}
++cnt[fl];
auto [node, par, it] = q[fl].front();
q[fl].pop();
int i = *it;
if (i != par && s[fl].find(i) == s[fl].end()) {
s[fl].insert(i);
if (!adj[i].empty()) {
q[fl].emplace(i, node, adj[i].begin());
}
}
auto nit = std::next(it);
if (nit != adj[node].end()) {
if (*nit == par) {
nit = std::next(nit);
if (nit != adj[node].end()) {
q[fl].emplace(node, par, std::next(it));
}
} else {
q[fl].emplace(node, par, std::next(it));
}
}
}
if (q[0].empty() && (!q[1].empty() || s[0].size() < s[1].size())) {
std::swap(u, v);
std::swap(s[0], s[1]);
}
dbg(cnt);
auto *ns = new std::set<int>(std::move(s[1]));
br.push_back(br.back() + static_cast<int64_t>(ns->size()) *
(static_cast<int64_t>(cc[u]->size()) -
static_cast<int64_t>(ns->size())));
for (int i : *ns) {
cc[u]->erase(i);
cc[i] = ns;
}
};
for (int i = 0; i < q; ++i) {
int tt;
std::cin >> tt;
if (tt == 1) {
int64_t xp, yp;
std::cin >> xp >> yp;
int x = static_cast<int>(e == 0 ? xp : (xp ^ last));
int y = static_cast<int>(e == 0 ? yp : (yp ^ last));
--x;
--y;
add(x, y);
br.push_back(br.back());
} else if (tt == 2) {
int64_t xp, yp;
std::cin >> xp >> yp;
int x = static_cast<int>(e == 0 ? xp : (xp ^ last));
int y = static_cast<int>(e == 0 ? yp : (yp ^ last));
--x;
--y;
rem(x, y);
join.push_back(join.back());
} else {
int64_t tp;
std::cin >> tp;
int t = static_cast<int>(e == 0 ? tp : (tp ^ last));
join.push_back(join.back());
br.push_back(br.back());
last = join[i + 1] - br[i - t + 1];
std::cout << last << '\n';
}
}
}