#include<fstream>
#include<iostream>
#include<vector>
#include<bitset>
#define nmax 100005
using namespace std;
int n,m1;
int nrlanturi;
int poz[nmax];
int lant[nmax];
int nivel[nmax];
int val[nmax];
int tata[nmax];
vector<int> m[nmax];
vector< vector<int> > lanturi;
vector< vector<int> > arbint;
vector<int> parinte;
bitset<nmax> viz;
int dfs(int nod,int niv)
{
int subarbmax=-1,subarb,df,nrfii=0,ok;
viz[nod]=1;
nivel[nod]=niv;
ok=1;
for(vector<int>::iterator it=m[nod].begin();it!=m[nod].end();it++)
if(!viz[*it])
{
tata[*it]=nod;
ok=0;
df=dfs(*it,niv+1);
if(subarbmax<df)
{
subarbmax=df;
subarb=lant[*it];
}
nrfii+=df;
}
if(ok)
{
vector<int> aux;
aux.push_back(nod);
poz[nod]=0;
lant[nod]=nrlanturi;
lanturi.push_back(aux);
parinte.push_back(tata[nod]);
nrlanturi++;
return 1;
}
poz[nod]=lanturi[ subarb ].size();
lant[nod]=subarb;
lanturi[subarb].push_back(nod);
parinte[ subarb ] = tata[nod];
return nrfii+1;
}
void update(int pozvecarb, int st,int dr,int p,int val,int poz)
{
if(st==dr)
{
arbint[pozvecarb][p]=val;
return;
}
int mij= st + (dr-st)/2;
if( mij< poz) update(pozvecarb,mij+1,dr,2*p+1,val,poz);
else update(pozvecarb,st,mij,2*p,val,poz);
arbint[pozvecarb][p]=max( arbint[pozvecarb][2*p], arbint[ pozvecarb][2*p+1] );
}
int querry(int pozvecarb,int st,int dr,int p,int a,int b)
{
if( st>=a && dr<=b ) return arbint[pozvecarb][p];
int maxi=-5,mij = st + (dr-st)/2;
if( mij < b ) maxi=max(maxi,querry(pozvecarb,mij+1,dr,2*p+1,a,b));
if( mij >= a) maxi=max(maxi,querry(pozvecarb,st,mij,2*p,a,b));
return maxi;
}
int main()
{
int i,j;
ifstream t1("heavypath.in");
ofstream t2("heavypath.out");
t1>>n>>m1;
for(i=1;i<=n;i++)
{
t1>>val[i];
}
int a,b;
for(i=1;i<n;i++)
{
t1>>a>>b;
m[a].push_back(b);
m[b].push_back(a);
}
dfs(1,0); //constructie lanturi
/*for(i=0;i<nrlanturi;i++)
cout<<parinte[i]<<' '; cout<<'\n';
for(i=1;i<=n;i++)
cout<<lant[i]<<' '; cout<<'\n';
for(i=1;i<=n;i++)
cout<<poz[i]<<' '; cout<<'\n';
for(i=1;i<=n;i++)
cout<<nivel[i]<<' '; cout<<'\n';
for(i=0;i<lanturi.size();i++)
{
for(j=0;j<lanturi[i].size();j++)
cout<<lanturi[i][j]<<' '<<val[lanturi[i][j]]<<" "; cout<<'\n';
}*/
for(i=0;i<nrlanturi;i++) //fac arborii de intervale
{
vector<int> aux;
arbint.push_back(aux);
arbint[i].resize(4*lanturi[i].size());
for(j=0;j<lanturi[i].size();j++)
update(i,1,lanturi[i].size(),1,val[lanturi[i][j]],j+1);
}
/*for(i=0;i<nrlanturi;i++)
{
for(j=1;j<arbint[i].size();j++) cout<<arbint[i][j]<<' '; cout<<'\n';
}*/
int c,sol;
for(;m1;m1--)
{
t1>>a>>b>>c;
// cout<<a<<' '<<b<<' '<<c<<'\n';
if(a==0)
{
update(lant[b],1,lanturi[ lant[b] ].size(),1,c,poz[b]+1);
}
else
{
sol=0;
while( lant[b]!=lant[c] )
{
if( nivel[ parinte[lant[b] ]] > nivel[ parinte [ lant[a] ] ] )
{
sol=max(sol, querry(lant[b],1,lanturi[ lant[b]].size(),1, poz[b]+1, lanturi[ lant[b]].size() ) );
b=parinte[ lant[b]];
}
else
{
sol=max(sol, querry(lant[c],1,lanturi[ lant[c]].size(),1, poz[c]+1, lanturi[ lant[c]].size() ) );
c=parinte[lant[c]];
}
}
sol=max(sol,querry(lant[c],1,lanturi[ lant[c]].size(),1, min( poz[c]+1,poz[b]+1) , max(poz[c]+1,poz[b]+1) ) );
t2<<sol<<'\n';
}
}
t1.close();
t2.close();
return 0;
}