#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;
typedef struct celula {
int nod;
celula *next;
} *lista;
lista graf[100005],v,lant[100005];
int lev[100005];
int tata[100005],i,j,n,m,t,a,b,val[100005];
int heavy[100005];
int chain_poz[100005], in_chain[100005], chain_sz[100005];
int nrl;
int *aint[100005];
int aux[100005];
void build_metadata(int nod, int l) {
lev[nod]=l;
int maxh=0, heaviest=-1;
heavy[nod]=1;
for (lista p=graf[nod]; p; p=p->next)
if (p->nod!=tata[nod]) {
tata[p->nod]=nod;
build_metadata(p->nod,l+1);
heavy[nod]+=heavy[p->nod];
if (heavy[p->nod]>maxh) { maxh=heavy[p->nod]; heaviest=p->nod; }
}
if (heaviest==-1) {
++nrl;
v=new celula; v->nod=nod; v->next=0; lant[nrl]=v;
in_chain[nod]=nrl;
chain_sz[nrl]=1;
}
else {
v=new celula; v->nod=nod; v->next=lant[in_chain[heaviest]]; lant[in_chain[heaviest]]=v;
in_chain[nod]=in_chain[heaviest];
++chain_sz[in_chain[nod]];
}
}
void init(int nod, int l, int r, int idx) {
if (l==r) aint[idx][nod]=aux[l];
else {
int mid=(l+r)/2;
init(2*nod,l,mid,idx);
init(2*nod+1,mid+1,r,idx);
aint[idx][nod]=max(aint[idx][2*nod],aint[idx][2*nod+1]);
}
}
void update(int idx,int nod, int l, int r, int poz, int v) {
if (l==r) aint[idx][nod]=v;
else {
int mid=(l+r)/2;
if (poz<=mid) update(idx,2*nod,l,mid,poz,v);
else update(idx,2*nod+1,mid+1,r,poz,v);
aint[idx][nod]=max(aint[idx][2*nod],aint[idx][2*nod+1]);
}
}
int query(int idx, int nod, int l, int r, int x, int y) {
if (l>=x && r<=y) return aint[idx][nod];
else {
int mid=(l+r)/2;
int vl=0, vr=0;
if (x<=mid) vl=query(idx,2*nod,l,mid,x,y);
if (y>mid) vr=query(idx,2*nod+1,mid+1,r,x,y);
return max(vl,vr);
}
}
int getMax(int x, int y) {
int sol=0;
while (in_chain[x]!=in_chain[y]) {
if (lev[lant[in_chain[x]]->nod]<lev[lant[in_chain[y]]->nod]) swap(x,y);
sol=max(sol,query(in_chain[x],1,1,chain_sz[in_chain[x]],1,chain_poz[x]));
x=tata[lant[in_chain[x]]->nod];
}
if (chain_poz[x]>chain_poz[y]) swap(x,y);
return max(sol,query(in_chain[x],1,1,chain_sz[in_chain[x]],chain_poz[x],chain_poz[y]));
}
int main(void) {
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin>>n>>m;
for (i=1; i<=n; ++i) cin>>val[i];
for (i=1; i<n; ++i) {
int x,y;
cin>>x>>y;
v=new celula; v->nod=x; v->next=graf[y]; graf[y]=v;
v=new celula; v->nod=y; v->next=graf[x]; graf[x]=v;
}
build_metadata(1,1);
//build aints
for (i=1; i<=nrl; ++i) {
aint[i]=new int[4*chain_sz[i]+4];
int j=1;
for (lista p=lant[i]; p; p=p->next, ++j){
chain_poz[p->nod]=j;
aux[j]=val[p->nod];
}
init(1,1,chain_sz[i],i);
}
//run queries
for (i=1; i<=m; ++i) {
int op, x,y;
cin>>op>>x>>y;
if (op==0) {
val[x]=y;
update(in_chain[x],1,1,chain_sz[in_chain[x]],chain_poz[x],y);
}
else {
cout<<getMax(x,y)<<"\n";
}
}
return 0;
}