#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int Nmax=100010;
int N,M,nrL;
vector<int>G[Nmax],P[Nmax];
int v[Nmax],fol[Nmax],niv[Nmax],w[Nmax],l[Nmax],arb[4*Nmax];
int lTata[Nmax],lNiv[Nmax],lDim[Nmax],lPoz[Nmax];
struct operatie
{
int t,x,y;
}op[Nmax];
void citire()
{
int x,y;
fin>>N>>M;
for(int i=1;i<=N;i++) fin>>v[i];
for(int i=1;i<N;i++)
{
fin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1;i<=M;i++) fin>>op[i].t>>op[i].x>>op[i].y;
}
void dfs(int nod)
{
w[nod]=1;
fol[nod]=1;
int hN=-1,frunza=1;
for(vector<int>::iterator it=G[nod].begin();it!=G[nod].end();it++)
{
if(fol[*it]) continue;
frunza=0;
niv[*it]=niv[nod]+1;
dfs(*it);
w[nod]+=w[*it];
if(hN==-1) hN=*it;
else if(w[*it]>w[hN]) hN=*it;
}
if(frunza)
{
l[nod]=++nrL;
lDim[nrL]=1;
P[nrL].push_back(nod);
return;
}
l[nod]=l[hN];
lDim[l[nod]]++;
P[l[nod]].push_back(nod);
for(vector<int>::iterator it=G[nod].begin();it!=G[nod].end();it++)
{
if( *it==hN || niv[*it]<niv[nod]) continue;
lTata[l[*it]]=nod;
lNiv[l[*it]]=niv[nod];
}
}
void build(int nod,int st,int dr,int decalaj,int lant)
{
if(st==dr) arb[nod+decalaj]=v[P[lant][st-1]];
else
{
int mid=(st+dr)/2;
build(nod*2,st,mid,decalaj,lant);
build(nod*2+1,mid+1,dr,decalaj,lant);
arb[nod+decalaj]=max(arb[nod*2+decalaj],arb[nod*2+1+decalaj]);
}
}
void make_paths()
{
niv[1]=1;
dfs(1);
for(int i=1;i<=nrL;i++)
{
reverse(P[i].begin(),P[i].end());
if(i>1) lPoz[i]=lPoz[i-1]+lDim[i-1]*4;
build(1,1,lDim[i],lPoz[i],i);
}
}
void update(int nod,int st,int dr,int poz,int val,int decalaj)
{
if(st==dr) arb[nod+decalaj]=val;
else
{
int mid=(st+dr)/2;
if(poz<=mid) update(nod*2,st,mid,poz,val,decalaj);
else update(nod*2+1,mid+1,dr,poz,val,decalaj);
arb[nod+decalaj]=max(arb[nod*2+decalaj],arb[nod*2+1+decalaj]);
}
}
int querry(int nod,int st,int dr,int a,int b,int decalaj)
{
if(a<=st && b>=dr) return arb[nod+decalaj];
else
{
int mid=(st+dr)/2,rez=0;
if(a<=mid) rez=querry(nod*2,st,mid,a,b,decalaj);
if(b>mid) rez=max(rez,querry(nod*2+1,mid+1,dr,a,b,decalaj));
return rez;
}
}
void solve()
{
int t,x,y,sol=0;
for(int i=1;i<=M;i++)
{
t=op[i].t;x=op[i].x;y=op[i].y;
if(t==0) update(1,1,lDim[l[x]],niv[x]-lNiv[l[x]],y,lPoz[l[x]]);
else
{
sol=0;
while(1)
{
if(l[x]==l[y])
{
if(niv[x]>niv[y]) swap(x,y);
sol=max(sol,querry(1,1,lDim[l[x]],niv[x]-lNiv[l[x]],niv[y]-lNiv[l[x]],lPoz[l[x]]));
break;
}
if(lNiv[l[x]]<lNiv[l[y]]) swap(x,y);
sol=max(sol,querry(1,1,lDim[l[x]],1,niv[x]-lNiv[l[x]],lPoz[l[x]]));
x=lTata[l[x]];
}
fout<<sol<<"\n";
}
}
}
int main()
{
citire();
make_paths();
solve();
}