#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int val[MAXN], nivel[MAXN], pos[MAXN], lant[MAXN], sub[MAXN], anc[MAXN];
vector<int> graf[MAXN], arb[MAXN], hpd[MAXN];
int lanturi;
void HPDInit(int nod, int tata){
anc[nod] = tata;
nivel[nod] = nivel[tata] + 1;
sub[nod] = 1;
for(auto x:graf[nod]){
if(x == tata) continue;
HPDInit(x, nod);
sub[nod] += sub[x];
}
if(sub[nod] == 1){
lanturi++;
hpd[lanturi].push_back(nod);
lant[nod] = lanturi;
return;
}
int best = 0;
for(auto x:graf[nod]){
if(x == tata) continue;
if(sub[x] > sub[best]) best = x;
}
lant[nod] = lant[best];
hpd[lant[nod]].push_back(nod);
pos[nod] = (int)hpd[lant[nod]].size() - 1;
}
void ArbInit(int nod, int st, int dr, int lant){
if(st == dr){
arb[lant][nod] = val[hpd[lant][st]];
return;
}
int mij = (st + dr) / 2;
ArbInit(2 * nod, st, mij, lant);
ArbInit(2 * nod + 1, mij + 1, dr, lant);
arb[lant][nod] = max(arb[lant][2 * nod], arb[lant][2 * nod + 1]);
}
int query(int nod, int st, int dr, int a, int b, int lant){
if(a <= st && dr <= b)
return arb[lant][nod];
int mij = (st + dr) / 2;
int maxst = -1, maxdr = -1;
if(a <= mij) maxst = query(2 * nod, st, mij, a, b, lant);
if(b > mij) maxdr = query(2 * nod + 1, mij + 1, dr, a, b, lant);
return max(maxst, maxdr);
}
void update(int nod, int st, int dr, int pozit, int val, int lant){
if(st == dr && st == pozit){
arb[lant][nod] = val;
return;
}
int mij = (st + dr) / 2;
if(pozit <= mij) update(2 * nod, st, mij, pozit, val, lant);
else update(2 * nod + 1, mij + 1, dr, pozit, val, lant);
arb[lant][nod] = max(arb[lant][2 * nod], arb[lant][2 * nod + 1]);
}
int findMax(int x, int y){
int ans = -3;
if(lant[x] == lant[y]){
int st = min(pos[x], pos[y]), dr = max(pos[x], pos[y]);
ans = max(ans, query(1, 0, (int)hpd[lant[x]].size() - 1, st, dr, lant[x]));
}
else{
if(nivel[hpd[lant[x]][0]] < nivel[hpd[lant[y]][0]]) swap(x, y);
ans = max(ans, query(1, 0, (int)hpd[lant[x]].size() - 1, 0, pos[x], lant[x]));
ans = max(ans, findMax(anc[hpd[lant[x]][0]], y));
}
return ans;
}
int main()
{
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, m;
fin >> n >> m;
for(int i = 1; i <= n; ++i)
fin >> val[i];
for(int i = 1; i < n; ++i){
int x, y;
fin >> x >> y;
graf[x].push_back(y);
graf[y].push_back(x);
}
HPDInit(1, 0);
for(int i = 1; i <= lanturi; ++i)
reverse(hpd[i].begin(), hpd[i].end());
for(int i = 1; i <= n; ++i)
pos[i] = (int)hpd[lant[i]].size() - 1 - pos[i];
for(int i = 1; i <= lanturi; ++i){
arb[i].resize((int)hpd[i].size() << 2);
ArbInit(1, 0, (int)hpd[i].size() - 1, i);
}
while(m){
int op, x, y;
fin >> op >> x >> y;
if(op) fout << findMax(x, y) << "\n";
else update(1, 0, hpd[lant[x]].size() - 1, pos[x], y, lant[x]);
m--;
}
return 0;
}