#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,bit=20;
int n,T,root[N],node;
struct segtree{
int l,r,f,siz;
segtree(){
l=r=f=siz=0;
}
}t[N*bit];
void clone(int &u){
t[++node]=t[u],u=node;
}
int build(int u,int l,int r){
clone(u);
if(l==r){
t[u].f=l,t[u].siz=1;
return u;
}
int mid=(l+r)/2;
t[u].l=build(t[u].l,l,mid),t[u].r=build(t[u].r,mid+1,r);
return u;
}
int query(int u,int l,int r,int x){
if(l==r){
return t[u].f;
}
int mid=(l+r)/2;
if(x<=mid){
return query(t[u].l,l,mid,x);
}
return query(t[u].r,mid+1,r,x);
}
int find(int ver,int x){
if(query(root[ver],1,n,x)==x){
return x;
}
return find(ver,query(root[ver],1,n,x));
}
int query2(int u,int l,int r,int x){
if(l==r){
return t[u].siz;
}
int mid=(l+r)/2;
if(x<=mid){
return query2(t[u].l,l,mid,x);
}
return query2(t[u].r,mid+1,r,x);
}
int update(int u,int l,int r,int fx,int fy,int ver){
clone(u);
if(l==r){
t[u].siz+=query2(root[ver],1,n,fx),t[u].f=fy;
return u;
}
int mid=(l+r)/2;
if(fx<=mid){
t[u].l=update(t[u].l,l,mid,fx,fy,ver);
}
else{
t[u].r=update(t[u].r,mid+1,r,fx,fy,ver);
}
return u;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>T,root[0]=build(1,1,n);
for(int typ,a,b,i=1;i<=T;i++){
cin>>typ>>a;
if(typ==1){
cin>>b;
if(query2(root[i-1],1,n,a)>query2(root[i-1],1,n,b)){
swap(a,b);
}
int fx=find(i-1,query(root[i-1],1,n,a)),fy=find(i-1,query(root[i-1],1,n,b));
if(fx!=fy){
root[i]=update(root[i-1],1,n,fx,fy,i-1);
}
else{
root[i]=root[i-1];
}
}
if(typ==2){
root[i]=root[a];
}
if(typ==3){
cin>>b,root[i]=root[i-1];
if(find(i,a)==find(i,b)){
cout<<"1\n";
}
else{
cout<<"0\n";
}
}
}
}