#include <fstream>
#include <algorithm>
#include <vector>
#define NMAX 10
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
struct nodeType{
vector<int>edge;
int grupa, ordNumber, depth;
}arb[NMAX + 1];
int pLight[NMAX + 1];
int aintGlobal[NMAX * 4], sizeOfGrupa[NMAX + 1], pozStartCur;
int* pozStartAint[NMAX + 1];
int v[NMAX + 1];
int dfs(int node, int p) {
if(p != 0 && arb[node].edge.size() == 1) {
arb[node].grupa = node;
arb[node].ordNumber = 1;
sizeOfGrupa[node] = 1;
return 1;
}
int mxCopii = 0, vecinHeavy, vecin, nrCopii, totalCopii = 0;
for(int i = 0; i < arb[node].edge.size(); i++) {
vecin = arb[node].edge[i];
if(vecin == p) {
continue;
}
arb[vecin].depth = arb[node].depth + 1;
nrCopii = dfs(vecin, node);
totalCopii += nrCopii;
if(nrCopii > mxCopii) {
mxCopii = nrCopii;
vecinHeavy = vecin;
}
}
for(int i = 0; i < arb[node].edge.size(); i++) {
vecin = arb[node].edge[i];
if(vecin == p) {
continue;
}
if(vecin != vecinHeavy) {
pLight[arb[vecin].grupa] = node;
pozStartAint[arb[vecin].grupa] = aintGlobal + pozStartCur;
pozStartCur += arb[vecin].ordNumber * 4;
} else {
arb[node].grupa = arb[vecin].grupa;
arb[node].ordNumber = arb[vecin].ordNumber + 1;
sizeOfGrupa[arb[node].grupa]++;
}
}
return totalCopii;
}
int query(int* aint, int p, int lInt, int rInt, int lTarget, int rTarget) {
if(lTarget <= lInt && rInt <= rTarget) {
return aint[p];
}
int med = (lInt + rInt) / 2, mx = 0;
if(lTarget <= med) {
mx = max(mx, query(aint, p * 2, lInt, med, lTarget, rTarget));
}
if(med + 1 <= rTarget) {
mx = max(mx, query(aint, p * 2 + 1, med + 1, rInt, lTarget, rTarget));
}
return mx;
}
void update(int* aint, int p, int lInt, int rInt, int target, int val) {
if(lInt == rInt) {
aint[p] = val;
return;
}
int med = (lInt + rInt) / 2;
if(target <= med) {
update(aint, p * 2, lInt, med, target, val);
}
if(med + 1 <= target) {
update(aint, p * 2 + 1, med + 1, rInt, target, val);
}
aint[p] = max(aint[p * 2], aint[p * 2 + 1]);
}
int main() {
/*
pozStartAint[0] = v + 5;
v[5] = 10;
v[6] = 12;
cout<<&v[5]<<" "<<pozStartAint[0][1]<<"\n";
return 0;
*/
int n, m, i, a, b, c;
cin>>n>>m;
for(i = 1; i <= n; i++) {
cin>>v[i];
}
for(i = 1; i < n; i++) {
cin>>a>>b;
arb[a].edge.push_back(b);
arb[b].edge.push_back(a);
}
arb[1].depth = 1;
dfs(1, 0);
pozStartAint[arb[1].grupa] = &aintGlobal[pozStartCur];
pozStartCur += arb[1].ordNumber * 4;
for(i = 1; i <= n; i++) {
update(pozStartAint[arb[i].grupa], 1, 1, sizeOfGrupa[arb[i].grupa], arb[i].ordNumber, v[i]);
}
for(i = 1; i <= m; i++) {
cin>>c>>a>>b;
if(c == 0) {
update(pozStartAint[arb[a].grupa], 1, 1, sizeOfGrupa[arb[a].grupa], arb[a].ordNumber, b);
} else {
int josa = arb[a].ordNumber, susa = sizeOfGrupa[arb[a].grupa], josb = arb[b].ordNumber, susb = sizeOfGrupa[arb[b].grupa], mx = 0;
while(arb[pLight[arb[a].grupa]].depth != arb[pLight[arb[b].grupa]].depth) {
if(arb[pLight[arb[a].grupa]].depth >= arb[pLight[arb[b].grupa]].depth) {
mx = max(mx, query(pozStartAint[arb[a].grupa], 1, 1, sizeOfGrupa[arb[a].grupa], josa, susa));
a = pLight[arb[a].grupa];
josa = arb[a].ordNumber;
susa = sizeOfGrupa[arb[a].grupa];
} else {
mx = max(mx, query(pozStartAint[arb[b].grupa], 1, 1, sizeOfGrupa[arb[b].grupa], josb, susb));
b = pLight[arb[b].grupa];
josb = arb[b].ordNumber;
susb = sizeOfGrupa[arb[b].grupa];
}
}
mx = max(mx, query(pozStartAint[arb[a].grupa], 1, 1, sizeOfGrupa[arb[a].grupa], min(arb[a].ordNumber, arb[b].ordNumber), max(arb[a].ordNumber, arb[b].ordNumber)));
cout<<mx<<"\n";
}
}
return 0;
}