#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << " "; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head struct Sustainable_DSU { static const int N = 2e5 + 5, M = 4e6 + 5; int root[N], lson[M], rson[M], fa[M], rnk[M], tot, n; inline void build(int &rt, int l, int r) { rt = ++tot; if(l == r) {fa[rt] = l; return ;} int m = l+r >> 1; build(lson[rt], l, m); build(rson[rt], m+1, r); } inline void init(int _n) { n = _n; tot = 0; build(root[0], 1, n); } inline void Update(int old, int &rt, int p, int v, int l, int r) { rt = ++tot; lson[rt] = lson[old], rson[rt] = rson[old]; if(l == r) { fa[rt] = v; rnk[rt] = rnk[old]; return ; } int m = l+r >> 1; if(p <= m) Update(lson[rt], lson[rt], p, v, l, m); else Update(rson[rt], rson[rt], p, v, m+1, r); } inline void update(int rt, int p, int l, int r) { if(l == r) { rnk[rt]++; return ;} int m = l+r >> 1; if(p <= m) update(lson[rt], p, l, m); else update(rson[rt], p, m+1, r); } ///返回rt版本p位置fa数组下标 inline int query(int rt, int p, int l, int r) { if(l == r) return rt; int m = l+r >> 1; if(p <= m) return query(lson[rt], p, l, m); else return query(rson[rt], p, m+1, r); } ///返回rt版本p所在并查集fa数组下标 inline int Find(int rt, int p) { int now = query(rt, p, 1, n); if(fa[now] == p) return now; else return Find(rt, fa[now]); } ///在i时刻合并x和y所在并查集 inline void Merge(int i, int x, int y) { root[i] = root[i-1]; int px = Find(root[i], x), py = Find(root[i], y); if(fa[px] != fa[py]) { if(rnk[px] > rnk[py]) swap(px, py); Update(root[i-1], root[i], fa[px], fa[py], 1, n); if(rnk[px] == rnk[py]) update(root[i], fa[py], 1, n); } } }s; int n, m, op, a, b; int main() { scanf("%d %d", &n, &m); s.init(n); for (int i = 1; i <= m; ++i) { scanf("%d", &op); if(op == 1) scanf("%d %d", &a, &b), s.Merge(i, a, b); else if(op == 2) scanf("%d", &a), s.root[i] = s.root[a]; else { scanf("%d %d", &a, &b); s.root[i] = s.root[i-1]; a = s.Find(s.root[i], a); b = s.Find(s.root[i], b); if(s.fa[a] == s.fa[b]) printf("1 "); else printf("0 "); } } return 0; }