#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int nmax = 100000;
vector <int> v[nmax + 5];
int a[4*nmax + 5];
int val[nmax + 5];
int sz[nmax + 5];
int hv[nmax + 5];
int idd[nmax + 5];
int t[nmax + 5];
int lv[nmax + 5];
int r[nmax + 5];
int inv[nmax + 5];
int n,m;
int o;
void df1(int nod)
{
sz[nod]=1;
lv[nod]=lv[t[nod]]+1;
for(auto& i : v[nod]){
if(t[nod]==i) continue;
t[i]=nod;
df1(i);
sz[nod]+=sz[i];
if(sz[i] > sz[hv[nod]])
hv[nod] = i;
}
}
void build(int nod,int st,int dr)
{
if(st==dr) {a[nod] = val[inv[st]]; return;}
int mid = (st+dr)/2;
build(nod*2,st,mid);
build(nod*2+1,mid+1,dr);
a[nod]=max(a[nod*2],a[nod*2+1]);
}
void update(int nod,int st,int dr,int poz,int x)
{
if(st==dr) {a[nod] = x; return;}
int mid = (st+dr)/2;
if(poz<=mid) update(nod*2,st,mid,poz,x);
else update(nod*2+1,mid+1,dr,poz,x);
a[nod]=max(a[nod*2],a[nod*2+1]);
}
int query(int nod,int st,int dr,int x,int y)
{
if(x<=st && dr<=y) return a[nod];
int mid = (st+dr)/2;
int s1=0,s2=0;
if(x<=mid) s1 = query(nod*2,st,mid,x,y);
if(y>mid) s2 = query(nod*2+1,mid+1,dr,x,y);
return max(s1,s2);
}
void mk(int nod,int head)
{
r[nod] = head;
idd[nod]=++o;
inv[o]=nod;
if(hv[nod])
mk(hv[nod],head);
for(auto& i : v[nod]) if(i!=t[nod] && i!=hv[nod]) mk(i,i);
}
int query_path(int x,int y)
{
int sol = 0;
while(r[x]!=r[y])
{
if(lv[r[x]] > lv[r[y]]) swap(x,y);
sol=max(sol,query(1,1,n,idd[r[y]],idd[y]));
y=t[r[y]];
}
if(lv[x] > lv[y]) swap(x,y);
sol=max(sol,query(1,1,n,idd[x],idd[y]));
return sol;
}
int main()
{
fin>>n>>m;
for(int i=1;i<=n;i++) fin>>val[i];
for(int i=1;i<n;i++)
{
int x,y;
fin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
df1(1);
mk(1,1);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int t;
fin>>t;
if(t==0)
{
int x,y;
fin>>x>>y;
update(1,1,n,idd[x],y);
}
else
{
int x,y;
fin>>x>>y;
fout<<query_path(x,y)<<'\n';
}
}
}