#include <algorithm>
#include <vector>
#include <stdio.h>
using namespace std;
#define N_MAX 100001
#define LEFT (nod << 1)
#define RIGHT ((nod << 1) | 1)
int cost[N_MAX], tata[N_MAX], fii[N_MAX];
int lungime[N_MAX], drumuri, poz[N_MAX], tataDrum[N_MAX], nivel[N_MAX];
bool ut[N_MAX];
vector <int> aint[N_MAX];
vector <int> graf[N_MAX];
int n, m, i, j, x, y, op;
//****//
//vector <int> d[N_MAX];
//***//
void heavypath(int nod, int niv){
ut[nod] = 1;
nivel[nod] = niv;
if(graf[nod].size() == 1 && nod != 1){
fii[nod] = 1;
drumuri ++;
tata[nod] = drumuri;
poz[nod] = ++ lungime[drumuri];
return ;
}
int nodMax = 0;
for(int i = 0; i < (int)graf[nod].size(); i ++){
if(ut[graf[nod][i]])
continue;
heavypath(graf[nod][i], niv + 1);
fii[nod] += fii[graf[nod][i]];
if(fii[graf[nod][i]] > fii[nodMax])
nodMax = graf[nod][i];
}
for(int i = 0; i < (int)graf[nod].size(); i ++){
if(graf[nod][i] != nodMax)
tataDrum[tata[graf[nod][i]]] = nod;
}
tata[nod] = tata[nodMax];
poz[nod] = ++ lungime[tata[nod]];
}
int INDEX, POZ, VAL, ST, DR;
void update(int nod, int st, int dr){
if(st == dr){
aint[INDEX][nod] = VAL;
return ;
}
int mid = (st + dr) >> 1;
if(POZ <= mid)
update(LEFT, st, mid);
if(POZ > mid)
update(RIGHT, mid + 1, dr);
aint[INDEX][nod] = max(aint[INDEX][LEFT], aint[INDEX][RIGHT]);
}
int query(int nod, int st, int dr){
if(ST <= st && dr <= DR)
return aint[INDEX][nod];
int mid = (st + dr) >> 1;
int rez = 0;
if(ST <= mid)
rez = max(rez, query(LEFT, st, mid));
if(mid < DR)
rez = max(rez, query(RIGHT, mid + 1, dr));
return rez;
}
int lca(int x, int y){
int Max = 0;
while(tata[x] != tata[y])
if(nivel[tataDrum[tata[x]]] > nivel[tataDrum[tata[y]]]){
INDEX = tata[x]; ST = 1; DR = poz[x];
Max = max(Max, query(1, 1, lungime[tata[x]]));
x = tataDrum[tata[x]];
}
else{
INDEX = tata[y]; ST = 1; DR = poz[y];
Max = max(Max, query(1, 1, lungime[tata[y]]));
y = tataDrum[tata[y]];
}
INDEX = tata[x]; ST = min(poz[x], poz[y]); DR = max(poz[x], poz[y]);
Max = max(Max, query(1, 1, lungime[tata[x]]));
return Max;
}
int main(){
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d %d", &n, &m);
for(i = 1; i <= n; i ++)
scanf("%d", &cost[i]);
for(i = 1; i < n; i ++){
scanf("%d %d", &x, &y);
graf[x].push_back(y);
graf[y].push_back(x);
}
heavypath(1, 1);
for(i = 1; i <= drumuri; i ++)
aint[i].resize(4 * lungime[i] + 10);
for(i = 1; i <= n; i ++){
poz[i] = lungime[tata[i]] + 1 - poz[i];
INDEX = tata[i]; POZ = poz[i]; VAL = cost[i];
update(1, 1, lungime[tata[i]]);
}
//Opearatii
for(i = 1; i <= m; i ++){
scanf("%d %d %d", &op, &x, &y);
if(op == 0){
INDEX = tata[x]; POZ = poz[x]; VAL = y;
update(1, 1, lungime[tata[x]]);
}
else{
printf("%d\n",lca(x, y));
}
}
/*********************
for(i = 1; i <= n; i ++){
if(d[tata[i]].empty())
d[tata[i]].resize(lungime[tata[i]] + 1);
d[tata[i]][poz[i]] = i;
}
for(i = 1; i <= drumuri; i ++){
for(j = 1; j < d[i].size(); j ++)
printf("%d ", d[i][j]);
printf(" -> %d", tata[d[i][1]]);
printf(" | tataDrum -> %d", tataDrum[i]);
printf("\n");
}
*/
return 0;
}