#include <bits/stdc++.h>
#define DIM 100005
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int n, q, nrLanturi, v[DIM], t[DIM], desc[DIM], depth[DIM], nrLant[DIM], aint[4 * DIM], Start[DIM], P[DIM];
vector <int> lant[DIM];
vector <int> edges[DIM];
bitset <DIM> used;
void dfs(int nod, int niv, int tata)
{
used[nod] = 1;
depth[nod] = niv;
desc[nod] = 1;
int maxDesc = 0, fiuMaxDesc;
for(auto child : edges[nod])
if(!used[child])
{
dfs(child, niv + 1, nod);
desc[nod] += desc[child];
if(maxDesc < desc[child])
{
maxDesc = desc[child];
fiuMaxDesc = child;
}
}
if(maxDesc == 0)
{
lant[++nrLanturi].push_back(nod);
nrLant[nod] = nrLanturi;
t[nrLanturi] = tata;
}
else
{
lant[nrLant[fiuMaxDesc]].push_back(nod);
nrLant[nod] = nrLant[fiuMaxDesc];
t[nrLant[fiuMaxDesc]] = tata;
}
}
void Update(int nod, int st, int dr, int poz, int val, int decalaj)
{
if(st == dr)
{
aint[nod + decalaj] = val;
return ;
}
int mid = (st + dr) / 2;
if(mid >= poz)
Update(2 * nod, st, mid, poz, val, decalaj);
else
Update(2 * nod + 1, mid + 1, dr, poz, val, decalaj);
aint[nod + decalaj] = max(aint[2 * nod + decalaj], aint[2 * nod + 1 + decalaj]);
}
int Query(int nod, int st, int dr, int stQ, int drQ, int decalaj)
{
if(stQ <= st && dr <= drQ)
{
return aint[nod + decalaj];
}
int mid = (st + dr) / 2, r1(0), r2(0);
if(mid >= stQ)
r1 = Query(2 * nod, st, mid, stQ, drQ, decalaj);
if(mid < drQ)
r2 = Query(2 * nod + 1, mid + 1, dr, stQ, drQ, decalaj);
return max(r1, r2);
}
int main()
{
f >> n >> q;
for(int i = 1; i <= n; i++)
f >> v[i];
for(int i = 1; i < n; i++)
{
int x, y;
f >> x >> y;
edges[x].push_back(y);
edges[y].push_back(x);
}
dfs(1, 1, 0);
for(int i = 1; i <= nrLanturi; i++)
{
int j, k;
Start[i] = Start[i - 1] + 4 * lant[i - 1].size();
for(j = 0, k = lant[i].size() - 1; j < k; j++, k--)
{
swap(lant[i][j], lant[i][k]);
P[lant[i][j]] = j;
P[lant[i][k]] = k;
}
P[lant[i][j]] = j;
}
for(int i = 1; i <= n; i++)
Update(1, 0, lant[nrLant[i]].size() - 1, P[i], v[i], Start[nrLant[i]]);
for(; q; q--)
{
int ops, x, y;
f >> ops >> x >> y;
if(ops == 0)
{
Update(1, 0, lant[nrLant[x]].size() - 1, P[x], y, Start[nrLant[x]]);
}
else
{
int ans = 0;
while(1)
{
int l1 = nrLant[x];
int l2 = nrLant[y];
if(l1 == l2)
{
ans = max(ans, Query(1, 0, lant[l1].size() - 1, min(P[x], P[y]), max(P[x], P[y]), Start[l1]));
break;
}
else
{
if(depth[t[l1]] > depth[t[l2]])
{
ans = max(ans, Query(1, 0, lant[l1].size() - 1, 0, P[x], Start[l1]));
x = t[l1];
}
else
{
ans = max(ans, Query(1, 0, lant[l2].size() - 1, 0, P[y], Start[l2]));
y = t[l2];
}
}
}
g << ans << "\n";
}
}
return 0;
}