#include <bits/stdc++.h>
#define NMAX 100009
#define LOG 40
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int val[NMAX];
int sizen[NMAX];
int pinc[NMAX];
int level[NMAX];
int fatherchain[NMAX];
int n,m,nrc,sol;
int v[NMAX];
int wchain[NMAX];///carui apartine
bool uz[NMAX];
vector <int>a[NMAX];
vector <int>g[NMAX];
vector <int>chain[NMAX];
void citire();
void query(int x,int y);
void dfs(int k, int tata);
void build(int chain, int nod, int st, int dr);
void update(int ch,int nod, int st, int dr, int poz, int val);
void query_aint(int ch, int nod, int st, int dr, int x, int y, int &maxi);
///astea sunt pentru caz simplu
int main()
{citire();
dfs(1,0);
for(int i=1;i<=nrc;i++){
for(int j=0;j<2*chain[i].size();j++)
a[i].push_back(0);
build(i,1,1,chain[i].size()-1);
}
///le am bilduit pe toate
for(int i=1;i<=m;i++)
{
int op,x,y;
fin>>op>>x>>y;
if(!op)
update(wchain[x],1,1,chain[wchain[x]].size()-1,pinc[x],y);
else
{
sol=0;
query(x,y);
fout<<sol<<'\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-1;i++)
{
fin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
}
void dfs(int k, int tata)
{int i;bool ok=0;
uz[k]=1;sizen[k]=1;level[k]=level[tata]+1;
for(i=0;i<g[k].size();i++)
if(!uz[g[k][i]])
dfs(g[k][i],k),ok=1,sizen[k]+=sizen[g[k][i]];
///acum ca am pregatit pentru el vedem daca e fr
if(!ok)///e frunza
{
chain[++nrc].push_back(0);
chain[nrc].push_back(k);
wchain[k]=nrc;
pinc[k]=1;
}
else
{
int maxim=0;int poz=0;///pun direct fiul
for(i=0;i<g[k].size();i++)
if(g[k][i]!=tata)
if(sizen[g[k][i]]>maxim) { maxim=sizen[g[k][i]];poz=g[k][i];}
chain[wchain[poz]].push_back(k);
wchain[k]=wchain[poz];
pinc[k]=chain[wchain[poz]].size()-1;
///acum face parte din chain, e tata pt doar restul
for(i=0;i<g[k].size();i++)
if(g[k][i]!=tata && g[k][i]!=poz)
fatherchain[wchain[g[k][i]]]=k;
}
}
void build(int ch, int nod, int st, int dr)
{
if(st==dr)
{a[ch][nod]=v[chain[ch][st]];return;}
int mj=(st+dr)/2;
build(ch,2*nod,st,mj);
build(ch,2*nod+1,mj+1,dr);
a[ch][nod]=max(a[ch][2*nod],a[ch][2*nod+1]);
}
void update(int ch, int nod, int st, int dr, int poz, int val)
{
if(st==dr)
{a[ch][nod]=val;return;}
int mj=(st+dr)/2;
if(poz<=mj)
update(ch,2*nod,st,mj,poz,val);
else
update(ch,2*nod+1,mj+1,dr,poz,val);
a[ch][nod]=max(a[ch][2*nod],a[ch][2*nod+1]);
}
void query_aint(int ch, int nod, int st, int dr, int x, int y, int &maxi)
{
if(x<=st && dr<=y)
{maxi=max(maxi,a[ch][nod]);return;}
int mj=(st+dr)/2;
if(x<=mj)
query_aint(ch,2*nod,st,mj,x,y,maxi);
if(y>mj)
query_aint(ch,2*nod+1,mj+1,dr,x,y,maxi);
}
void query(int x,int y)
{
if(wchain[x]==wchain[y])///caz banal
{
int maxi=0;
int posx=pinc[x];
int posy=pinc[y];
if(posx>posy)
swap(posx,posy);
query_aint(wchain[x],1,1,chain[wchain[x]].size()-1,posx,posy,maxi);
sol=max(sol,maxi);
return;
}
if(level[fatherchain[wchain[x]]]>level[fatherchain[wchain[y]]])
{
int maxi=0;
query_aint(wchain[x],1,1,chain[wchain[x]].size()-1,pinc[x],chain[wchain[x]].size()-1,maxi);
sol=max(sol,maxi);
int nr=fatherchain[wchain[x]];
query(nr,y);
}
else
{
int maxi=0;
query_aint(wchain[y],1,1,chain[wchain[y]].size()-1,pinc[y],chain[wchain[y]].size()-1,maxi);
sol=max(sol,maxi);
int nr=fatherchain[wchain[y]];
query(x,nr);
}
}