#include<bits/stdc++.h> using namespace std; inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x*f; } const int maxm = 10000005, maxn = 200005; struct node { int l, r, ls, rs, v, deep; } tr[maxm]; int n, m, sz, rt[maxn], last; inline void build(int &k, int l, int r) { if (!k)k = ++sz; tr[k].l = l; tr[k].r = r; if (l == r) { tr[k].v = l; return; } int mid = (l + r) >> 1; build(tr[k].ls, l, mid); build(tr[k].rs, mid + 1, r); } inline void update(int l, int r, int x, int &y, int pos, int val) { y = ++sz; if (l == r) { tr[y].v = val; return; } tr[y].ls = tr[x].ls; tr[y].rs = tr[x].rs; int mid = (l + r) >> 1; if (pos <= mid)update(l, mid, tr[x].ls, tr[y].ls, pos, val); else update(mid + 1, r, tr[x].rs, tr[y].rs, pos, val); } inline int query(int k, int l, int r, int x) { if (l == r)return k; int mid = (l + r) >> 1; if (x <= mid)return query(tr[k].ls, l, mid, x); else return query(tr[k].rs, mid + 1, r, x); } inline void add(int k, int l, int r, int pos) { if (l == r) { tr[k].deep++; return; } int mid = (l + r) >> 1; if (pos <= mid)add(tr[k].ls, l, mid, pos); else add(tr[k].rs, mid + 1, r, pos); } inline int find(int k, int x) { int p = query(k, 1, n, x); if (x == tr[p].v)return p; return find(k, tr[p].v); } int main() { n = read(); m = read(); build(rt[0], 1, n); int f, k, a, b; for (int i = 1; i <= m; i++) { f = read(); if (f == 1) { rt[i] = rt[i - 1]; a = read(); b = read(); int p = find(rt[i], a), q = find(rt[i], b); if (tr[p].v == tr[q].v)continue; if (tr[p].deep > tr[q].deep)swap(p, q); update(1, n, rt[i - 1], rt[i], tr[p].v, tr[q].v); if (tr[p].deep == tr[q].deep)add(rt[i], 1, n, tr[q].v); } if (f == 2) { k = read(); rt[i] = rt[k]; } if (f == 3) { rt[i] = rt[i - 1]; a = read(); b = read(); int p = find(rt[i], a), q = find(rt[i], b); if (tr[p].v == tr[q].v)last = 1; else last = 0; printf("%d\n", last); } } return 0; }