rt
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define min(a,b) (a<b?a:b)
#define P pair<int,int>
#define x first
#define y second
#define rd read()
#define modd(x) (((x)%mod+mod)%mod)
#define rd read()
#define lowbit(x) ((x)&(-x))
inline int read(int u=0, char c=getchar(), bool f=false){
for (;!isdigit(c);c=getchar()) f|=c=='-';
for (;isdigit(c);c=getchar()) u=(u<<1)+(u<<3)+c-'0';
return f?-u:u;
}
inline void wt(int x){
if(x<0) x=-x,putchar('-');
if(x>9) wt(x/10);
putchar(x%10+48);
}
inline void wt(int x,char c){wt(x),putchar(c);}
const int inf=~0U>>1;
const int N=1e5+10;
struct node{
int l,r,fa,siz;
}tr[N<<5];
int n,m,cnt;
int root[N<<5];
void build(int &now,int l,int r){
now=++cnt;
if(l==r){
tr[now].fa=l,tr[now].siz=1;
return ;
}
int mid=l+r>>1;
build(tr[now].l,l,mid);
build(tr[now].r,mid+1,r);
}
int query(int now,int l,int r,int pos){
if(l==r) return now;
int mid=l+r>>1;
if(pos<=mid) return query(tr[now].l,l,mid,pos);
else return query(tr[now].r,mid+1,r,pos);
}
void insert(int pre,int &now,int l,int r,int pos,int x){
now=++cnt;
tr[now]=tr[pre];
if(l==r) return ;
int mid=l+r>>1;
if(pos<=mid||x<=mid) insert(tr[pre].l,tr[now].l,l,mid,pos,x);
if(pos>mid||x>mid) insert(tr[pre].r,tr[now].r,mid+1,r,pos,x);
}
int find(int now,int x){
int fa=query(root[now],1,n,x);
if(tr[fa].fa==x) return x;
return find(now,tr[fa].fa);
}
void merge(int now,int x,int y){
int a=find(now,x),b=find(now,y);
insert(root[now-1],root[now],1,n,a,b);
a=query(root[now],1,n,a),b=query(root[now],1,n,b);
if(tr[a].siz<tr[b].siz) tr[a].fa=tr[b].fa,tr[b].siz+=tr[a].siz;
else tr[b].fa=tr[a].fa,tr[a].siz+=tr[b].siz;
}
main(){
n=rd,m=rd;
build(root[0],1,n);
for(int i=1;i<=m;i++){
int t=rd,a=rd;
root[i]=root[i-1];
if(t==1) merge(i,a,rd);
if(t==2) root[i]=root[a];
if(t==3) wt((find(i,a)==find(i,rd)),'\n');
}
return 0;
}