include
using namespace std;
define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k'-') f=-1;
while(isdigit(k)) res=res10+k-'0',k=getchar();
return resf;
}
const int N=1e5+10;
int fa[N],ls[N],rs[N],l[N],r[N],dfn[N],tot,anc[N][20];
int head[N],cnt,dep[N],n,m;
struct node{
int to,nxt;
}e[N<<1];
inline void add(int u,int v)
{
e[++cnt].nxt=head[u]; e[cnt].to=v;
return head[u]=cnt,void();
}
inline void dfs(int x,int fat)
{
dep[x]=dep[fat]+1; dfn[++tot]=x; l[x]=tot; anc[x][0]=fat; fa[x]=fat;
for(int i=1;(1< for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fat) dfs(e[i].to,x);
r[x]=tot;
return ;
}
inline int lca(int x,int y)
{
if(dep[x]
if(x
for(int i=19;i>=0;--i) if(anc[x][i]!=anc[y][i]) x=anc[x][i],y=anc[y][i];
return anc[x][0];
}
struct tree{
int maxx,fl,l,r;
#define maxx(p) t[p].maxx
#define l(p) t[p].l
#define r(p) t[p].r
#define fl(p) t[p].fl
}t[N<<2];
inline void push_up(int x){return maxx(x)=max(maxx(x<<1),maxx(x<<1|1)),void();}
inline void build(int p,int st,int ed)
{
l(p)=st; r(p)=ed;
if(sted) return maxx(p)=dep[dfn[st]],void();
int mid=(st+ed)>>1; build(p<<1,st,mid); build(p<<1|1,mid+1,ed);
return push_up(p);
}
inline void push_down(int p)
{
if(fl(p))
{
fl(p<<1)+=fl(p); maxx(p<<1)+=fl(p);
maxx(p<<1|1)+=fl(p); fl(p<<1|1)+=fl(p);
} return fl(p)=0,void();
}
inline void update(int p,int st,int ed,int val)
{
if(stl(p)&&r(p)ed) return fl(p)+=val,maxx(p)+=val,void();
int mid=(l(p)+r(p))>>1; push_down(p);
if(ed<=mid) update(p<<1,st,ed,val);
else if(st>mid) update(p<<1|1,st,ed,val);
else update(p<<1,st,mid,val),update(p<<1|1,mid+1,ed,val);
return push_up(p);
}
inline int query(int p,int st,int ed)
{
if(stl(p)&&r(p)ed) return maxx(p);
int mid=(l(p)+r(p))>>1; push_down(p);
if(ed<=mid) return query(p<<1,st,ed);
if(st>mid) return query(p<<1|1,st,ed);
return max(query(p<<1|1,mid+1,ed),query(p<<1,st,mid));
}
inline bool isroot(int x){return ls[fa[x]]!=x&&rs[fa[x]]!=x;}
inline void rotate(int x)
{
int y=fa[x],z=fa[y];
if(!isroot(y)) if(ls[z]y) ls[z]=x; else rs[z]=x;
if(ls[y]x) ls[y]=rs[x],fa[rs[x]]=y,rs[x]=y;
else rs[y]=ls[x],fa[ls[x]]=y,ls[x]=y;
fa[x]=z; fa[y]=x;
return ;
}
inline void splay(int x)
{
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if(!isroot(y)) rotate((ls[y]x)^(ls[z]y)?x:y);
rotate(x);
} return ;
}
inline int findroot(int x){while(ls[x]) x=ls[x]; return x;}
inline void access(int x)
{
for(int y=0;x;x=fa[y=x])
{
splay(x);
if(rs[x])
{
int t=rs[x]; t=findroot(t);
update(1,l[t],r[t],1);
} rs[x]=y;
if(rs[x])
{
int t=rs[x]; t=findroot(t);
update(1,l[t],r[t],-1);
}
} return ;
}
signed main()
{
n=read(); m=read();
for(int i=1,u,v;i
while(m--)
{
int opt=read();
if(opt
if(opt2)
{
int x=read(),y=read(),lc=lca(x,y);
x=l[x],y=l[y],lc=l[lc];
printf("%lld\n",query(1,x,x)+query(1,y,y)-2*query(1,lc,lc)+1);
}
if(opt3)
{
int x=read();
printf("%lld\n",query(1,l[x],r[x]));
}
}
return 0;
}
}
signed main(){return yspm::main();}