#include<iostream>
#include<fstream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int N = 100100;
int n, m, x[N], sizeSubArb[N], niv[N];
vector<int> v[N];
bool ver[N];
void calcSiz(int nod) {
ver[nod] = 1;
sizeSubArb[nod] = 1;
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it]) {
niv[*it] = niv[nod] + 1;
calcSiz(*it);
sizeSubArb[nod] += sizeSubArb[*it];
}
}
int nrl, lant[N], size[N], pozNod[N], pLant[N], firstNod[N];
vector<int> aint[N];
void calcLant(int nod, int lantc) {
ver[nod] = 1;
pozNod[nod] = ++size[lantc];
lant[nod] = lantc;
int sizMax = 0;
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it])
sizMax = max(sizMax, sizeSubArb[*it]);
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it] && sizeSubArb[*it] == sizMax) {
calcLant(*it, lantc);
break;
}
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it]) {
++nrl;
firstNod[nrl] = *it;
pLant[nrl] = nod;
calcLant(*it, nrl);
}
}
void update(int lant, int nod, int pozx, int pozy, int poz, int val) {
if(pozx == pozy) {
aint[lant][nod] = val;
return;
}
int mid = (pozx + pozy) / 2;
if(mid >= poz)
update(lant, 2 * nod, pozx, mid, poz, val);
else
update(lant, 2 * nod + 1, mid + 1, pozy, poz, val);
aint[lant][nod] = max(aint[lant][2 * nod], aint[lant][2 * nod + 1]);
}
int query(int lant, int nod, int pozx, int pozy, int poz1, int poz2) {
if(poz1 > poz2)
swap(poz1, poz2);
if(poz1 <= pozx && pozy <= poz2)
return aint[lant][nod];
int mid = (pozx + pozy) / 2, rez = 0;
if(mid >= poz1)
rez = query(lant, 2 * nod, pozx, mid, poz1, poz2);
if(mid < poz2)
rez = max(rez, query(lant, 2 * nod + 1, mid + 1, pozy, poz1, poz2));
return rez;
}
int maxLant(int nod1, int nod2) {
int rez = 0;
while(lant[nod1] != lant[nod2]) {
if(niv[firstNod[lant[nod1]]] < niv[firstNod[lant[nod2]]])
swap(nod1, nod2);
rez = max(rez, query(lant[nod1], 1, 1, size[lant[nod1]], 1, pozNod[nod1]));
nod1 = pLant[lant[nod1]];
}
rez = max(rez, query(lant[nod1], 1, 1, size[lant[nod1]], pozNod[nod1], pozNod[nod2]) );
return rez;
}
int main() {
int i;
in >> n >> m;
for(i = 1; i <= n; ++i)
in >> x[i];
for(i = 1; i < n; ++i) {
int a, b;
in >> a >> b;
v[a].push_back(b);
v[b].push_back(a);
}
calcSiz(1);
memset(ver, 0, sizeof(ver));
firstNod[1] = 1;
calcLant(1, ++nrl);
for(i = 1; i <= nrl; ++i)
aint[i].resize(4 * size[i]);
for(i = 1; i <= n; ++i)
update(lant[i], 1, 1, size[lant[i]], pozNod[i], x[i]);
for(i = 1; i <= m; ++i) {
int op, a, b;
in >> op >> a >> b;
if(!op)
update(lant[a], 1, 1, size[lant[a]], pozNod[a], b);
else
cout << maxLant(a, b) << "\n";
}
return 0;
}