#include <bits/stdc++.h>
#define NMAX 100100
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n,m,nrc ;
int v[NMAX];
int lvl[NMAX];
bool uz[NMAX];
int nrf[NMAX];
int whatc[NMAX];
int positioninchain[NMAX];
int fatherch[NMAX];
vector <int>g[NMAX];
vector <int>chain[NMAX];
int a[NMAX][30];
int x,y,op,i,j;
void citire();
void build(int ch, int node, int st, int dr);
void df(int k, int lvl, int fath);
int querya_int(int ch, int node, int st, int dr, int x, int y);
int query_r(int x, int y);
void update(int ch, int node, int st, int dr, int poz, int val);
int main()
{citire();
df(1,0,0);
//fout<<chain[whatc[9]].size();
/* for (i=1;i<=nrc;i++)
for (int j=0;j<2*chain[i].size();j++)
a[i].push_back(0);*/
for(i=1;i<=nrc;i++)
build(i,1,1,chain[i].size()-1);
//fout<<query_r(6,8);
//fout<<v[9];
for(i=1;i<=m;i++)
{
fin>>op>>x>>y;
if(op==0)
update(whatc[x],1,1,chain[whatc[x]].size()-1,positioninchain[x],y);
else
{
fout<<query_r(x,y)<<'\n';
}
}
return 0;
}
void citire()
{int i,x,y;
fin>>n>>m;
for(i=1;i<=n;i++)
fin>>v[i];
for(i=1;i<n;i++)
{
fin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
}
void df(int k,int niv, int tata)
{int i;
bool ok=0;
///prima data
uz[k]=1; nrf[k]=1;lvl[k]=niv;
///
for(i=0;i<g[k].size();i++)
if(!uz[g[k][i]])
{
ok=1;
df(g[k][i],niv+1,k);
nrf[k]+=nrf[g[k][i]];
}
if(!ok) ///frunza
{chain[++nrc].push_back(0);
chain[nrc].push_back(k);
//fout<<nrc<<" "<<chain[nrc][0]<<'\n';
whatc[k]=nrc;
positioninchain[k]=1;
}
else
{
int maxim=0;int care=-1;
for(i=0;i<g[k].size();i++)
if( nrf[g[k][i]]>maxim && g[k][i]!=tata)
{maxim=nrf[g[k][i]];care=g[k][i];}
// fout<<care<<" ";
chain[whatc[care]].push_back(k);
whatc[k]=whatc[care];
positioninchain[k]=chain[whatc[care]].size()-1;
///la momentul asta tatal e chiar k pt toate celalt(e in exterior)
for(i=0;i<g[k].size();i++)
if(g[k][i]!=care && g[k][i]!=tata)
{
fatherch[whatc[g[k][i]]]=k;
}
}
}
void build(int ch, int node, int st, int dr)
{
if(st==dr)
{a[ch][node]=v[chain[ch][st] ];return;}
int mj=(st+dr)/2;
build(ch,2*node,st,mj);
build(ch,2*node+1,mj+1,dr);
a[ch][node]=max(a[ch][2*node],a[ch][2*node+1]);
}
int querya_int(int ch, int node, int st, int dr, int x, int y)
{int val1=0,val2=0;
if(x<=st && dr<=y)
return a[ch][node];
int mj=(st+dr)/2;
if(x<=mj)
val1=querya_int(ch,2*node,st,mj,x,y);
if(y>mj)
val2=querya_int(ch,2*node+1,mj+1,dr,x,y);
return max(val1,val2);
}
int query_r(int x, int y)
{int maxim=0;
int tata;
if(whatc[x]==whatc[y])
{
//x=positioninchain[x];
//y=positioninchain[y];
if(positioninchain[x]>positioninchain[y])
swap(x,y);
return querya_int(whatc[x],1,1,chain[whatc[x]].size()-1,positioninchain[x],positioninchain[y]);
}
if(lvl[fatherch[whatc[x]]] > lvl[fatherch[whatc[y]]] )
{int max2=0;
max2= querya_int(whatc[x],1,1,chain[whatc[x]].size()-1,positioninchain[x],chain[whatc[x]].size()-1) ;
maxim= max(max2,maxim);
tata=fatherch[whatc[x]];
maxim=max(maxim,query_r(tata,y) );
}
else
{
maxim=max(maxim, querya_int(whatc[y],1,1,chain[whatc[y]].size()-1,positioninchain[y],chain[whatc[y]].size()-1) );
tata=fatherch[whatc[y]];
maxim=max(maxim,query_r(tata,x) );
}
return maxim;
}
void update(int ch, int node, int st, int dr, int poz, int val)
{//fout<<node<<" ";
if(st==dr)
{a[ch][node]=val;return;}
int mj=(st+dr)/2;
if(poz<=mj)
update(ch,2*node,st,mj,poz,val);
else
update(ch,2*node+1,mj+1,dr,poz,val);
a[ch][node]=max(a[ch][2*node],a[ch][2*node+1]);
}