#include <bits/stdc++.h>
#define NMAX 100010
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int heavy[NMAX],lv[NMAX],poz[NMAX],head[NMAX],tree[4*NMAX],pr[NMAX],pp[NMAX],val[NMAX];
vector<int>v[NMAX];
int n,q,o;
void build(int node,int left,int right)
{
if(left==right)
{
tree[node]=val[pp[left]];
return;
}
int mij=(left+right)/2;
build(2*node,left,mij);
build(2*node+1,mij+1,right);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
void update(int node,int left,int right,int pos,int val)
{
if(left==right)
{
tree[node]=val;
return;
}
int mij=(left+right)/2;
if(pos<=mij)
update(2*node,left,mij,pos,val);
else
update(2*node+1,mij+1,right,pos,val);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
int query(int node,int left,int right,int st,int dr)
{
if(st<=left && right<=dr)
return tree[node];
int mij=(left+right)/2,a=0,b=0;
if(st<=mij)
a=query(2*node,left,mij,st,dr);
if(mij<dr)
b=query(2*node+1,mij+1,right,st,dr);
return max(a,b);
}
int dfs(int node,int parent)
{
lv[node]=lv[parent]+1;
pr[node]=parent;
int total=1;
int maxi=0;
for(auto it:v[node])
if(it!=parent)
{
int cnt=dfs(it,node);
total+=cnt;
if(cnt>maxi)
maxi=cnt,heavy[node]=it;
}
return total;
}
void create_path(int node,int hd,int parent)
{
head[node]=hd;
++o;
pp[o]=node;
poz[node]=o;
if(heavy[node]!=0) ///nu este frunza si rezolv direct hld-ul
create_path(heavy[node],hd,node);
for(auto it:v[node])
if(it!=parent && it!=heavy[node])
create_path(it,it,node); ///incep eu un nou lant
}
int query_hld(int a,int b)
{
int maxi=0;
while(head[a]!=head[b])
{
if(lv[head[a]]>lv[head[b]])
swap(a,b);
maxi=max(maxi,query(1,1,n,poz[head[b]],poz[b]));
b=pr[head[b]];
}
if(lv[a]>lv[b])
swap(a,b);
maxi=max(maxi,query(1,1,n,poz[a],poz[b]));
return maxi;
}
int main()
{
fin>>n>>q;
for(int i=1;i<n;i++)
{
int x,y;
fin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0);
create_path(1,1,0);
build(1,1,n);
while(q--)
{
int t,x,y;
fin>>t>>x>>y;
if(t==1)
update(1,1,n,poz[x],y);
else
fout<<query_hld(x,y)<<'\n';
}
return 0;
}