#include <cstdio>
FILE* in=fopen("heavypath.in","r");
FILE* out=fopen("heavypath.out","w");
const int Q=200007;
struct node;
int maxim(const int &a,const int &b)
{
return a>b?a:b;
}
int partitie[3*Q];
struct arbore
{
int mg;
void change(int p, int st, int dr, int poz, int val)
{
if(st==dr)
{
partitie[mg+p]=val;
return;
}
int md=(st+dr)/2;
if(poz<=md)
{
change(p*2,st,md,poz,val);
}
else
{
change(p*2+1,md+1,dr,poz,val);
}
partitie[mg+p]=maxim(partitie[mg+2*p],partitie[mg+2*p+1]);
}
int give(int p, int st, int dr, int a, int b)
{
if(st>b || dr<a)
return 0;
if(st>=a && dr<=b)
return partitie[mg+p];
int md=(st+dr)/2;
return maxim(give(2*p,st,md,a,b),give(2*p+1,md+1,dr,a,b));
}
};
struct lant
{
node *varf;
int size;
arbore a;
void update(int poz, int val)
{
a.change(1,1,size, poz, val);
}
int ask(int st, int dr)
{
return a.give(1,1,size,st,dr);
}
}l[Q];
int nxtl=1;
struct node
{
int fii;
int h;
node *tata;
lant *l;
} v[Q];
void query(int x, int y)
{
int rez=0;
node *a=&v[x],*b=&v[y];
while(a->l!=b->l)
{
if(a->l->varf->tata->h > b->l->varf->tata->h)
{
rez=maxim(rez,a->l->ask(1,a->h - a->l->varf->h+1));
a=a->l->varf->tata;
}
else
{
rez=maxim(rez,b->l->ask(1,b->h - b->l->varf->h+1));
b=b->l->varf->tata;
}
}
if(a->h > b->h)
rez=maxim(rez,a->l->ask(b->h - b->l->varf->h+1 , a->h - a->l->varf->h+1));
else
rez=maxim(rez,a->l->ask(a->h - a->l->varf->h+1, b->h - b->l->varf->h+1));
fprintf(out,"%d\n",rez);
}
int cost[Q];
int n,q;
int lastpart;
void main2()
{
for(int i=1; i<=nxtl; i++)
{
l[i].a.mg=lastpart;
lastpart+=3*l[i].size;
}
for(int i=1; i<=n; i++)
{
v[i].l->update(v[i].h-v[i].l->varf->h+1 ,cost[i]);
}
int t,x,y;
for(int k=1; k<=q; k++)
{
fscanf(in,"%d%d%d",&t,&x,&y);
if(t==0)
{
v[x].l->update(v[x].h-v[x].l->varf->h+1,y);
}
else
{
query(x,y);
}
}
}
///------------------make lant
int lst[Q],val[2*Q],nxt[2*Q],nr;
void add(int a, int b)
{
val[++nr]=b;
nxt[nr]=lst[a];
lst[a]=nr;
}
void dfs2(int nod, int tata, int lt)
{
if(l[lt].size==0)
{
l[lt].varf=&v[nod];
}
l[lt].size++;
v[nod].l=&l[lt];
int max=0;
for(int p=lst[nod]; p; p=nxt[p])
{
if(val[p]!=tata)
{
if(v[max].fii<v[val[p]].fii)
max=val[p];
}
}
for(int p=lst[nod]; p; p=nxt[p])
{
if(val[p]!=tata)
{
if(max==val[p])
dfs2(val[p], nod, lt);
else
dfs2(val[p], nod, ++nxtl);
}
}
}
void dfs1(int nod, int tata)
{
v[nod].fii=1;
v[nod].h=v[tata].h+1;
v[nod].tata=&v[tata];
for(int p=lst[nod]; p; p=nxt[p])
{
if(val[p]!=tata)
{
dfs1(val[p],nod);
v[nod].fii+=v[val[p]].fii;
}
}
}
///------------------make lant
int main()
{
fscanf(in,"%d%d",&n,&q);
for(int i=1; i<=n; i++)
{
fscanf(in,"%d",&cost[i]);
}
int a,b;
for(int i=1; i<n; i++)
{
fscanf(in,"%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs1(1,0);
dfs2(1,0,1);
main2();
return 0;
}