using
namespace
std;
typedef
long
long ll;
const
int INF=
1e9;
const
double eps=
1e-9;
const
int maxn=
1e5+
10;
int to[maxn<<
1],nex[maxn<<
1],beg[maxn],dfn[maxn],id[maxn],f[maxn][
20],dep[maxn],size[maxn];
int e,dfs_time,n;
inline int (){
int x=
0,flag=
1;
char ch=getchar();
while(!
isdigit(ch) && ch!=
'-')ch=getchar();
if(ch==
'-')flag=
-1,ch=getchar();
while(
isdigit(ch))x=(x<<
3)+(x<<
1)+ch-
'0',ch=getchar();
return x*flag;
}
struct Seg_T{
int Seg[maxn<<
2],Tag[maxn<<
2];
void Build(int h,int l,int r){
if(l==r){
Seg[h]=dep[id[l]];
return;
}
int mid=(l+r)>>
1;
Build(h<<
1,l,mid),Build(h<<
1|
1,mid+
1,r);
Seg[h]=max(Seg[h<<
1],Seg[h<<
1|
1]);
}
inline void Push_Down(int h){
if(Tag[h]){
Tag[h<<
1]+=Tag[h],Seg[h<<
1]+=Tag[h];
Tag[h<<
1|
1]+=Tag[h],Seg[h<<
1|
1]+=Tag[h];
Tag[h]=
0;
}
}
void Modify(int h,int l,int r,int L,int R,int val){
if(L<=l && r<=R){
Seg[h]+=val,Tag[h]+=val;
return;
}
Push_Down(h);
int mid=(l+r)>>
1;
if(L<=mid)Modify(h<<
1,l,mid,L,R,val);
if(R>mid)Modify(h<<
1|
1,mid+
1,r,L,R,val);
Seg[h]=max(Seg[h<<
1],Seg[h<<
1|
1]);
}
int Query(int h,int l,int r,int L,int R){
if(L<=l && r<=R)
return Seg[h];
Push_Down(h);
int mid=(l+r)>>
1,ans=
0;
if(L<=mid)ans=max(ans,Query(h<<
1,l,mid,L,R));
if(R>mid)ans=max(ans,Query(h<<
1|
1,mid+
1,r,L,R));
return ans;
}
}Seg;
struct LCT{
#define rel(x) (ch[fa[x]][1]==x)
int ch[maxn][
2],fa[maxn];
inline int isroot(int x){
return ch[fa[x]][
0]!=x && ch[fa[x]][
1]!=x;
}
inline void Rotate(int x){
int y=fa[x],t=fa[y],flag=rel(x);
ch[fa[ch[x][flag^
1]]=y][flag]=ch[x][flag^
1];
fa[x]=t;
if(!isroot(y))ch[t][rel(y)]=x;
ch[fa[y]=x][flag^
1]=y;
}
inline void Splay(int x){
for(;!isroot(x);Rotate(x))
if(!isroot(fa[x]))Rotate(rel(x)^rel(fa[x])?x:fa[x]);
}
inline int Getl(int x){
while(ch[x][
0])x=ch[x][
0];
return x;
}
inline void Access(int x){
for(
int i=
0;x;x=fa[i=x]){
Splay(x);
if(ch[x][
1]){
int pos=Getl(ch[x][
1]);
Seg.Modify(
1,
1,n,dfn[pos],dfn[pos]+size[pos]
-1,
1);
}
ch[x][
1]=i;
if(i){
int pos=Getl(i);
Seg.Modify(
1,
1,n,dfn[pos],dfn[pos]+size[pos]
-1,
-1);
}
}
}
}T;
inline void add(int x,int y){
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
}
void dfs(int x,int fa){
int i;
dfn[x]=++dfs_time;id[dfs_time]=x;
f[x][
0]=fa;T.fa[x]=fa;size[x]=
1;
for(i=beg[x];i;i=nex[i]){
if(to[i]==fa)
continue;
dep[to[i]]=dep[x]+
1;
dfs(to[i],x);
size[x]+=size[to[i]];
}
}
inline int Get_LCA(int x,int y){
int i;
if(dep[x]<dep[y])swap(x,y);
for(i=
18;i>=
0;i--)
if((dep[x]-dep[y]) & (
1<<i))
x=f[x][i];
if(x==y)
return x;
for(i=
18;i>=
0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][
0];
}
int main(){
int i,j,q;
#ifndef ONLINE_JUDGE
freopen(
"BZOJ4817.in",
"r",
stdin);
freopen(
"BZOJ4817.out",
"w",
stdout);
#endif
n=read();q=read();
for(i=
1;i<n;i++){
int x=read(),y=read();
add(x,y);add(y,x);
}
dep[
1]=
1;dfs(
1,
0);
for(i=
1;i<=
18;i++)
for(j=
1;j<=n;j++)
f[j][i]=f[f[j][i
-1]][i
-1];
Seg.Build(
1,
1,n);
while(q--){
int opt=read();
if(opt==
1){
int x=read();
T.Access(x);
}
if(opt==
2){
int x=read(),y=read(),lca=Get_LCA(x,y);
int ans=Seg.Query(
1,
1,n,dfn[x],dfn[x])+Seg.Query(
1,
1,n,dfn[y],dfn[y]);
printf(
"%dn",ans
-2*Seg.Query(
1,
1,n,dfn[lca],dfn[lca])+
1);
}
if(opt==
3){
int x=read();
printf(
"%dn",Seg.Query(
1,
1,n,dfn[x],dfn[x]+size[x]
-1));
}
}
return
0;
}
|