#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int nmx=100005;
int n,i,j,nr,m,np,x,y,op,k,sol;
int ct[nmx],v[nmx],t[nmx],pth[nmx],pos[nmx];
vector<int> ad[nmx];
struct Path
{
int n,mx,tt,h;
vector<int> nd,ai;
void create()
{
ai.resize(4*n+5);
build(1,1,n);
}
void build(int n,int l,int r)
{
if(l==r)
{
ai[n]=nd[l-1];
return;
}
int m=(l+r)/2;
build(2*n,l,m);
build(2*n+1,m+1,r);
ai[n]=max(ai[2*n],ai[2*n+1]);
}
void update(int p,int v)
{
change(1,1,n,p,v);
}
void change(int n,int l,int r,int p,int v)
{
if(l==r)
{
ai[n]=v;
return;
}
int m=(l+r)/2;
if(p<=m) change(2*n,l,m,p,v);
else change(2*n+1,m+1,r,p,v);
ai[n]=max(ai[2*n],ai[2*n+1]);
}
int query(int a,int b)
{
mx=0;
maxim(1,1,n,a,b);
return mx;
}
void maxim(int n,int l,int r,int a,int b)
{
if(a<=l && r<=b)
{
mx=max(mx, ai[n]);
return;
}
int m=(l+r)/2;
if(a<=m) maxim(2*n,l,m,a,b);
if(b>m) maxim(2*n+1,m+1,r,a,b);
}
} pa[nmx];
void dfs_cate(int n)
{
ct[n]=1;
for(int i:ad[n])
if(!ct[i])
{
t[i]=n;
dfs_cate(i);
ct[n]+=ct[i];
}
}
void make_paths(int n,int nw,int tt,int h)
{
if(nw) {
np++;
pa[np].tt=tt;
pa[np].h=h;
}
pa[np].n++;
pa[np].nd.push_back(v[n]);
pth[n]=np;
pos[n]=(int)pa[np].nd.size();
int id=0;
for(int i:ad[n])
if(i!=t[n] && ct[i]>ct[id])
id=i;
for(int i:ad[n])
if(i!=t[n])
make_paths(i, (i==id)?0:1, n, h+1);
}
int main() {
fin>>n>>m;
for(i=1;i<=n;i++)
fin>>v[i];
for(i=1;i<n;i++)
{
fin>>x>>y;
ad[x].push_back(y);
ad[y].push_back(x);
}
t[1]=0;
dfs_cate(1);
make_paths(1,1,0,1);
for(i=1;i<=np;i++)
pa[i].create();
while(m--)
{
fin>>op>>x>>y;
if(op==0)
pa[pth[x]].update(pos[x], y);
else
{
sol=0;
while(1)
{
if(pth[x]==pth[y])
{
sol=max(sol, pa[pth[x]].query(min(pos[x],pos[y]), max(pos[x],pos[y])));
break;
}
if(pa[pth[x]].h<pa[pth[y]].h)
k=x, x=y, y=k;
sol=max(sol, pa[pth[x]].query(1,pos[x]));
x=pa[pth[x]].tt;
}
fout<<sol<<"\n";
}
}
}