This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/persistent_unionfind"
#include "../Utility/template.hpp"
#include "../Datastructure/undabledsu.hpp"
int main() {
int N, Q;
cin >> N >> Q;
dsu o(N);
vector<vector<vector<int>>> ivs(Q+1);
rep(qi, 0, Q) {
int t, k, u, v;
cin >> t >> k >> u >> v;
k++;
ivs[k].push_back({t, int(qi)+1, u, v});
}
vector<int> ans(Q+1, -1);
auto dfs = [&](auto f, int k, dsu& d) -> void {
for(auto a : ivs[k]) {
if(a[0] == 1) {
if(d.same(a[2], a[3])) ans[a[1]-1] = 1;
else ans[a[1]-1] = 0;
continue;
}
else {
d.merge(a[2], a[3]);
f(f, a[1], d);
d.undo();
}
}
};
dfs(dfs, 0, o);
rep(qi,0 ,Q) if(ans[qi] != -1) cout << ans[qi] << '\n';
}
#line 1 "verify/Datastructure_undabledsu.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/persistent_unionfind"
#line 1 "Utility/template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for (ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define TT template <typename T>
TT using vec = vector<T>;
template <class T1, class T2> bool chmin(T1 &x, T2 y) {
return x > y ? (x = y, true) : false;
}
template <class T1, class T2> bool chmax(T1 &x, T2 y) {
return x < y ? (x = y, true) : false;
}
struct io_setup {
io_setup() {
ios::sync_with_stdio(false);
std::cin.tie(nullptr);
cout << fixed << setprecision(15);
}
} io_setup;
/*
@brief verify用テンプレート
*/
#line 1 "Datastructure/undabledsu.hpp"
struct dsu {
using vi = vector<int>;
using vvi = vec<vi>;
struct dat {
int u, v;
ll x;
dat(){}
dat(int a, int b, ll c) : u(a), v(b), x(c) {}
};
vi par, sz, es;
vec<ll> val;
stack<dat> his;
int cc;
ll op(ll l, ll r) {return l + r;}
ll inv(ll x) {return -x;}
dsu(int n) {
par = vi(n);
sz = vi(n, 1);
es = vi(n, 0);
val = vec<ll>(n, 0);
cc = n;
iota(all(par), 0);
}
int leader(int u) {
while(par[u] != u) {
u = par[u];
}
return u;
}
bool same(int a, int b) {
return leader(a) == leader(b);
}
bool merge(int a, int b) {
a = leader(a), b = leader(b);
if(sz[a] < sz[b]) swap(a, b);
his.push(dat(a, b, val[a]));
if(a == b) {
es[a]++;
return false;
}
else {
cc--;
par[b] = a;
sz[a] += sz[b];
es[a] += es[b] + 1;
val[a] = op(val[a] , val[b]);
return true;
}
}
bool undo() {
if(his.empty()) return false;
dat p = his.top();
auto [u, v, x] = p;
his.pop();
par[v] = v;
es[u]--;
if(u != v) {
cc++;
sz[u] -= sz[v];
es[u] -= es[v];
val[u] = op(val[u], inv( val[v] ));
}
return true;
}
//以下、必要ないなら省く。
void set(int v, ll f) {//注意: 代入では無い
while(1) {
val[v] = op(val[v], f);
if(v == par[v]) break;
v = par[v];
}
}
ll get(int u) {
return val[leader(u)];
}
int size(int u) {//uが含まれる連結成分のサイズを返す
return sz[leader(u)];
}
int edgecnt(int u) {
return es[leader(u)];
}
int component_count() {
return cc;
}
vvi groups() {
int n = par.size();
vvi ms(n);
rep(v, 0, n) {
ms[leader(v)].push_back(v);
}
vvi res;
rep(i, 0, n) if(ms[i].size() > 0) {
res.push_back(ms[i]);
}
return res;
}
};
/*
@brief undable dsu
@docs doc/undodsu.md
*/
#line 4 "verify/Datastructure_undabledsu.test.cpp"
int main() {
int N, Q;
cin >> N >> Q;
dsu o(N);
vector<vector<vector<int>>> ivs(Q+1);
rep(qi, 0, Q) {
int t, k, u, v;
cin >> t >> k >> u >> v;
k++;
ivs[k].push_back({t, int(qi)+1, u, v});
}
vector<int> ans(Q+1, -1);
auto dfs = [&](auto f, int k, dsu& d) -> void {
for(auto a : ivs[k]) {
if(a[0] == 1) {
if(d.same(a[2], a[3])) ans[a[1]-1] = 1;
else ans[a[1]-1] = 0;
continue;
}
else {
d.merge(a[2], a[3]);
f(f, a[1], d);
d.undo();
}
}
};
dfs(dfs, 0, o);
rep(qi,0 ,Q) if(ans[qi] != -1) cout << ans[qi] << '\n';
}