#include<fstream>
#include<vector>
using namespace std;
#define max_n 100100
ifstream f("heavypath.in");
ofstream g("heavypath.out");
vector<int> L[max_n];
vector<int> Lant[max_n];
struct aib{
int max;
aib *st , *dr;
}*A[max_n];
int V[max_n] , CLant[max_n] , PLant[max_n] , S[max_n] , T[max_n] , Niv[max_n];
int op , x , y , v_max , k , n , m;
int D[max_n];
void read(){
int a , b;
f>>n>>m;
for(register int i = 1 ; i <= n ; i++)
f>>V[i];
for(register int i = 1 ; i < n ; i++){
f>>a>>b;
L[a].push_back(b);
L[b].push_back(a);
}
}
void dfs(int nod , int niv , int tata){
int nod2 , nod_max , maxim = -1;
S[nod] = 1; Niv[nod] = niv; T[nod] = tata;
for(unsigned int i = 0 ; i < L[nod].size() ; i++){
nod2 = L[nod][i];
if( nod2 == tata )
continue;
dfs(nod2 , niv + 1 , nod);
S[nod] += S[nod2];
if(S[nod2] > maxim) maxim = S[nod2] , nod_max = nod2;
}
if( L[nod].size() == 1 && nod != 1 ){
Lant[++k].push_back(1);
Lant[k].push_back(nod); D[k]++ ; CLant[nod] = k; PLant[nod] = D[k];
}
else{
int lant = CLant[nod_max];
Lant[lant].push_back(nod); D[lant]++; CLant[nod] = lant; PLant[nod] = D[lant];
}
}
inline int vMax(int a , int b){
return a>b?a:b;
}
void create(aib *T , int st , int dr , int lant){
if(st == dr)
T->max = V[Lant[lant][st]];
else{
int mid = ((st + dr) >> 1);
T->st = new aib; T->dr = new aib;
create(T->st , st , mid , lant);
create(T->dr , mid+1 , dr , lant);
T->max = vMax(T->st->max , T->dr->max);
}
}
void form_aib(){
for(int i = 1 ; i <= k ; i++){
A[i] = new aib;
create(A[i] , 1 , D[i] , i);
}
}
void update(aib *T , int st , int dr , int poz){
if(st == dr && st == poz)
T->max = V[x];
else{
int mid = ((st + dr) >> 1);
if(poz <= mid)
update(T->st , st , mid , poz);
else
update(T->dr , mid + 1 , dr , poz);
T->max = vMax(T->st->max , T->dr->max);
}
}
bool intersectie(int st , int dr , int a , int b){
if(a >= st && a <= dr) return 1;
if(b >= st && b <= dr) return 1;
if(st >= a && st <= b) return 1;
if(dr >= a && dr <= b) return 1;
return 0;
}
void querry(aib *T , int st , int dr , int a , int b){
if(st >= a && dr <= b)
v_max = vMax(v_max , T->max);
else{
int mid = ((st + dr) >> 1);
if(intersectie(st , mid , a , b))
querry(T->st , st , mid , a , b);
if(intersectie(mid+1 , dr , a , b))
querry(T->dr , mid+1 , dr , a , b);
}
}
void solve(){
while(m--){
f>>op>>x>>y;
switch(op){
case 0:
V[x] = y;
update( A[CLant[x]] , 1 , D[CLant[x]] , PLant[x] );
break;
default:
int l1 = CLant[x] , l2 = CLant[y] ; v_max = -1;
while(l1 != l2){
if(Niv[Lant[l1][D[l1]]] < Niv[Lant[l2][D[l2]]]){
querry(A[l2] , 1 , D[l2] , PLant[y] , D[l2]);
y = T[Lant[l2][D[l2]]];
}
else{
querry(A[l1] , 1 , D[l1] , PLant[x] , D[l1]);
x = T[Lant[l1][D[l1]]];
}
l1 = CLant[x] ; l2 = CLant[y];
}
int p1 = PLant[x] , p2 = PLant[y];
if(p2 < p1) swap(p1 , p2);
querry(A[l1] , 1 , D[l1] , p1 , p2);
g<<v_max<<"\n";
break;
}
}
}
int main(){
read();
dfs(1 , 1 , 0);
form_aib();
solve();
return 0;
}