#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define in() freopen("data","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
struct Tree
{
int l, r, fa;
} T[maxn<<5];
int root[maxn], cnt = 0;
int deep[maxn];//并查集深度
int n, m;
void build(int l, int r, int &x)//先建树,进行初始化,如果有多case记得cnt初始化为0
{
x = ++cnt;
if (l == r)
{
T[x].fa = l;
deep[l] = 1;
return ;
}
int mid = (l + r) >> 1;
build(l, mid, T[x].l);
build(mid + 1, r, T[x].r);
}
int query(int l, int r, int rt, int pos)//查询pos在线段树中的位置
{
if (l == r) return rt;
int mid = (l + r) >> 1;
if (mid >= pos) return query(l, mid, T[rt].l, pos);
else return query(mid + 1, r, T[rt].r, pos);
}
int find(int x, int cur)//并查集的找祖先
{
int pos = query(1, n, root[cur], x);
if (T[pos].fa != x)
return find(T[pos].fa, cur);
return T[pos].fa;
}
void update(int l, int r, int &x, int y, int pos, int fa)
{
T[++cnt] = T[y];//继承上一个版本
x = cnt;//与父节点连接
if (l == r)
{
T[x].fa = fa;//更新fa值
return ;
}
int mid = (l + r) >> 1;
if (mid >= pos) update(l, mid, T[x].l, T[y].l, pos, fa);
else update(mid + 1, r, T[x].r, T[y].r, pos, fa);
}
void mix(int x, int y, int cur)
{
int fx = find(x, cur), fy = find(y, cur);
if (deep[fx] > deep[fy]) swap(fx, fy);//按秩合并
if (fx == fy) return ;
deep[fy] += deep[fx];
update(1, n, root[cur], root[cur-1], fx, fy);//在线段树fx的位置上更新为fy
}
int main()
{
#ifdef LOCAL
in();
#endif
scanf("%d%d", &n, &m);
build(1, n, root[0]);
int cur = 0, lastans = 0;
while (m--)
{
int op, a, b, k;
scanf("%d", &op);
if (op == 1)
{
scanf("%d%d", &a, &b);
a ^= lastans;
b ^= lastans;
root[cur+1] = root[cur];
mix(a, b, ++cur);
}
else if (op == 2)
{
scanf("%d", &k);
k ^= lastans;
root[++cur] = root[k];//这里不建议改成cur = k ,因为他可能跳到前面后又跳回去,这样会覆盖掉历史版本
}
else
{
scanf("%d%d", &a, &b);
a ^= lastans;
b ^= lastans;
root[cur+1] = root[cur];
++cur;
lastans = (find(a, cur) == find(b, cur));
printf("%d\n", lastans);
}
}
return 0;
}
#include <bits/stdc++.h>
#include <cstdio>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
const int maxn = 2e5 + 10;
rope <int> *f[maxn];
rope <int> :: iterator it;
int id[maxn];
int n, m, op, a, b;
int find (int &t, int x)
{
if (f[t]->at(x) == x) return x;
int fa = find(t, f[t]->at(x));
if (fa == f[t]->at(x)) return fa;
f[t]->replace(x, fa);
return fa;
}
void mix(int &t, int x, int y)
{
int fx = find(t, x), fy = find(t, y);
f[t]->replace(fy, fx);
}
int lastans = 0;
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; ++i) id[i] = i;
f[0] = new rope<int>(id, id + n + 1);
for (int i = 1; i <= m; ++i)
{
f[i] = new rope <int>(*f[i-1]);
scanf("%d", &op);
if (op == 1)
{
scanf("%d%d", &a, &b);
mix(i, a ^ lastans, b ^ lastans);
}
else if (op == 2)
{
scanf("%d", &a);
f[i] = f[lastans^a];
}
else if (op == 3)
{
scanf("%d%d", &a, &b);
printf("%d\n", lastans = find(i, a ^ lastans) == find(i, b ^ lastans));
}
}
return 0;
}