#include <bits/stdc++.h>
using namespace std;
int a[100010],sz[100010],l,tata[100010],euler[100010],first[100010],nxt[100010],arb[400010],niv[100010],n;
vector<int> v[100010];
void dfs(int nod,int tat)
{
sz[nod]=1;
tata[nod]=tat;
if(v[nod].size()>1 && v[nod][0]==tat) swap(v[nod][0],v[nod][1]);
for(int i=0;i<v[nod].size();i++)
{
if(v[nod][i]==tat) continue;
niv[v[nod][i]]=niv[nod]+1;
dfs(v[nod][i],nod);
sz[nod]+=sz[v[nod][i]];
if(sz[v[nod][i]]>sz[v[nod][0]]) swap(v[nod][i],v[nod][0]);
}
}
void dfs1(int nod)
{
first[nod]=++l;
euler[l]=nod;
for(int i=0;i<v[nod].size();i++)
{
if(v[nod][i]==tata[nod]) continue;
if(i==0) nxt[v[nod][i]]=nxt[nod];
else nxt[v[nod][i]]=v[nod][i];
dfs1(v[nod][i]);
}
}
void update(int nod,int st,int dr,int poz,int val)
{
if(st==dr) arb[nod]=val;
else
{
int mid=(st+dr)/2;
if(poz<=mid) update(nod*2,st,mid,poz,val);
else update(nod*2+1,mid+1,dr,poz,val);
arb[nod]=max(arb[nod*2],arb[nod*2+1]);
}
}
int query(int nod,int st,int dr,int left,int right)
{
if(left<=st && dr<=right) return arb[nod];
int mid=(st+dr)/2,ans=0;
if(left<=mid) ans=max(ans,query(nod*2,st,mid,left,right));
if(mid<right) ans=max(ans,query(nod*2+1,mid+1,dr,left,right));
return ans;
}
int solve(int x,int y)
{
int ans=0;
while(nxt[x]!=nxt[y])
{
if(niv[nxt[x]]<niv[nxt[y]]) swap(x,y);
ans=max(ans,query(1,1,n,nxt[first[x]],first[x]));
x=tata[nxt[x]];
}
if(niv[x]>niv[y]) swap(x,y);
return max(ans,query(1,1,n,first[x],first[y]));
}
int main()
{
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
int m,x,y,t;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0);
dfs1(1);
for(int i=1;i<=n;i++) update(1,1,n,i,a[euler[i]]);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&t,&x,&y);
if(t==0) update(1,1,n,first[x],y);
else printf("%d\n",solve(x,y));
}
return 0;
}