#include<iostream>
#include<fstream>
#include<algorithm>
#include<vector>
using namespace std;
#define NMAX 100010
int n, m, noLant;
int v[NMAX], niv[NMAX], card[NMAX], lant[NMAX], lDim[NMAX], lDad[NMAX], lNiv[NMAX], lPoz[NMAX], arbInt[NMAX*4];
bool viz[NMAX];
vector<int> G[NMAX], L[NMAX];
void df(int nod){
vector<int>::iterator it;
viz[nod] = true;
card[nod] = 1;
int hn=-1;
bool frunza = true;
for(it=G[nod].begin(); it!=G[nod].end(); it++ ){
if(viz[*it]) continue;
frunza = false;
niv[*it] = niv[nod] + 1;
df(*it);
card[nod] += card[*it];
if(hn == -1) hn = *it;
else if(card[hn] < card[*it])
hn = *it;
}
if(frunza){ // => creaza lant nou
++noLant;
lant[nod] = noLant;
lDim[noLant] = 1;
L[noLant].push_back(nod);
return;
}
lant[nod] = lant[hn];
lDim[ lant[nod] ] ++;
L[ lant[nod] ].push_back(nod);
for(it=G[nod].begin(); it!=G[nod].end(); it++ ){
if( (*it) == hn || niv[nod] > niv[*it] )
continue;
lDad[ lant[*it] ] = nod;
lNiv[ lant[*it] ] = niv[nod];
}
}
void build( int nod, int left, int right, int decalaj, int lNo ){
if(left == right){
arbInt[decalaj + nod] = v[ L[lNo][left-1] ];
return;
}
int mid = (left + right)/2;
build(nod*2,left, mid,decalaj,lNo);
build(nod*2+1,mid+1,right,decalaj,lNo);
arbInt[decalaj+nod] = max( arbInt[decalaj+2*nod], arbInt[decalaj+2*nod+1] );
}
void update(int nod, int left, int right, int poz, int decalaj, int val ){
if(left==right){
arbInt[decalaj + nod] = val;
return;
}
int mid=(left+right)/2;
if(poz <= mid)
update(nod*2,left,mid,poz,decalaj,val);
else
update(nod*2+1,mid+1,right,poz,decalaj,val);
arbInt[decalaj+nod] = max( arbInt[decalaj+2*nod], arbInt[decalaj+2*nod+1] );
}
int query(int nod, int left, int right, int x, int y, int decalaj){
if( x <= left && right <= y)
return arbInt[decalaj + nod];
int mid = (left+right)/2, rez = 0;
if(x <= mid )
rez = max( rez , query(nod*2,left,mid,x,y,decalaj) );
if(mid < y)
rez = max( rez , query(nod*2+1,mid+1,right,x,y,decalaj) );
return rez;
}
int main(){
FILE *in = fopen("heavypath.in","r"), *out = fopen("heavypath.out","w");
int i,a,b,t,x,y,sol;
//citire date
fscanf(in,"%d %d",&n,&m);
for(i=1; i<=n; i++)
fscanf(in,"%d",&v[i]);
for(i=1; i<n; i++){
fscanf(in,"%i%i",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
//constructie lanturi
niv[1] = 1;
df(1);
//constr Arbore Intervale din lanturi
for(i=1; i<=noLant; i++){
reverse(L[i].begin(),L[i].end());
if(i>1) lPoz[i] = lPoz[i-1] + lDim[i-1]*4;
build(1, 1, lDim[i], lPoz[i], i);
}
while(m--){
fscanf(in,"%i%i%i",&t,&x,&y);
if(t==0)
update(1,1,lDim[lant[x]],niv[x]-lNiv[lant[x]],lPoz[lant[x]],y);
else{
sol=0;
while(1){
if(lant[x] == lant[y]){
if(niv[x] > niv[y])
swap(x,y);
sol = max(sol, query( 1, 1, lDim[lant[x]], niv[x] - lNiv[lant[x]], niv[y] - lNiv[lant[x]], lPoz[lant[x]] ) );
break;
}
if( lNiv[lant[x]] < lNiv[lant[y]] )
swap(x,y);
sol = max(sol, query(1, 1, lDim[lant[x]], 1, niv[x] - lNiv[lant[x]], lPoz[lant[x]] ) );
x = lDad[ lant[x] ];
}
fprintf(out,"%d\n",sol);
}
}
fclose(in), fclose(out);
return 0;
}