//HighFlow
#include <cstdio>
#include <vector>
#define fcat(c) while (c!='\n') fscanf(f,"%c",&c)
#define cat(c) while (c!='\n') scanf("%c",&c)
#define For(i,st,dr,k) for (int i=(st);i<=(dr);i+=(k))
#define ll (long long)
#define kfl(i,j) (a[(i)][(j)].c-a[(i)][(j)].f)
using namespace std;
FILE *f,*g;
vector <int> a[100100];
vector <int> inv[100100];
vector <int> arb[100100];
int msk[100100]; // inversul lui inv
int con[100100]; // marimea fiecarui lant
int from[100100]; // pe ce lant e nodul curent
bool bf[100100];
bool lant[100100];
int tnod[100100];
int t[100100]; // indicele lantului tata al unui lant
int G[100100]; //greutatea
int ax[100100];
int lvl[100100];
int cn,n,m;
int i,j,left,right,x,y,tip,pos;
void read()
{
int i,x,y;
fscanf(f,"%d%d",&n,&m);
for (i=1;i<=n;i++) fscanf(f,"%d",&ax[i]);
for (i=1;i<n;i++)
{
fscanf(f,"%d%d",&x,&y);
a[x].push_back(y);
a[y].push_back(x);
}
}
void pre_df(int x)
{
int s=1,i;
bf[x]=true;
for (i=0;i<a[x].size();i++)
if (!bf[a[x][i]])
{
pre_df(a[x][i]);
s+=G[a[x][i]];
}
G[x]=s;
}
void elimina(int x)
{
int i,mx,mxi;
int k=1;
while (1)
{
con[cn]=k;
lant[x]=true;
msk[x]=k;
from[x]=cn;
inv[cn].push_back(x);
mx=-1;
for (i=0;i<a[x].size();i++)
if (mx<G[a[x][i]] && from[a[x][i]]==false)
{
mx=G[a[x][i]];
mxi=a[x][i];
}
if (mx==-1) break;
k++;
x=mxi;
}
}
void descompun(int x,int tata,int lv)
{
int i;
bf[x]=true;
if (!lant[x])
{
inv[++cn].push_back(0);
lvl[cn]=lv;
tnod[x]=tata;
t[cn]=from[tata];
elimina(x);
arb[cn].resize(con[cn]*5);
}
for (i=0;i<a[x].size();i++)
if (!bf[a[x][i]])
descompun(a[x][i],x,lv+1);
}
void update(int k,int nod,int st,int dr,int val)
{
if (st==dr)
{
arb[k][nod]=val;
return;
}
int m=(st+dr)/2;
if (pos<=m)
update(k,nod*2,st,m,val);
else
update(k,nod*2+1,m+1,dr,val);
arb[k][nod]=max(arb[k][nod*2],arb[k][nod*2+1]);
}
int query(int k,int nod,int st,int dr)
{
if (left<=st && dr<=right)
return arb[k][nod];
int m=(st+dr)/2;
int r1=0,r2=0;
if (left<=m) r1=query(k,nod*2,st,m);
if (m<right) r2=query(k,nod*2+1,m+1,dr);
return max(r1,r2);
}
int solve(int x,int y)
{
int c1,c2,ans=0;
c1=from[x];
c2=from[y];
while (c1!=c2)
if (lvl[c1]>=lvl[c2])
{
left=1; right=msk[x];
ans=max(ans,query(c1,1,1,con[c1]));
x=tnod[inv[c1][1]]; c1=from[x];
}
else
{
left=1; right=msk[y];
ans=max(ans,query(c2,1,1,con[c2]));
y=tnod[inv[c2][1]]; c2=from[y];
}
left=min(msk[x],msk[y]); right=max(msk[x],msk[y]);
ans=max(ans,query(c1,1,1,con[c1]));
return ans;
}
int main()
{
f=fopen("heavypath.in","r");
g=fopen("heavypath.out","w");
read();
pre_df(1);
for (i=1;i<=n;i++) bf[i]=false;
descompun(1,0,1);
for (i=1;i<=n;i++)
{
pos=msk[i];
update(from[i],1,1,con[from[i]],ax[i]);
}
for (i=1;i<=m;i++)
{
fscanf(f,"%d%d%d",&tip,&x,&y);
if (tip==0)
{
pos=msk[x];
update(from[x],1,1,con[from[x]],y);
}
else
{
fprintf(g,"%d\n",solve(x,y));
}
}
return 0;
}