#include<fstream>
#include<vector>
#include<algorithm>
#define NMAX 100005
using namespace std;
vector<int> G[NMAX], p[NMAX];
int A[4 * NMAX];
int n, m, op, x, y, sol, qs;
int value[NMAX];
int np;
int niv[NMAX], wg[NMAX], wp[NMAX];
int ps[NMAX], pf[NMAX], pfniv[NMAX];
int dcj[NMAX];
bool u[NMAX];
ifstream _cin("heavypath.in");
ofstream _cout("heavypath.out");
void build(int st, int dr, int nod, int path, int decal)
{
if(st == dr)
{
A[nod + decal] = value[p[path][st - 1]];
return;
}
int mij = st + (dr - st) / 2;
build(st, mij, 2 * nod, path, decal);
build(mij + 1, dr, 2 * nod + 1, path, decal);
A[nod + decal] = max(A[2 * nod + decal], A[2 * nod + 1 + decal]);
}
void update(int st, int dr, int nod, int poz, int upd, int decal)
{
if(st == dr)
{
A[nod + decal] = upd;
return;
}
int mij = st + (dr - st) / 2;
if(poz <= mij)
{
update(st, mij, 2 * nod, poz, upd, decal);
}else
{
update(mij + 1, dr, 2 * nod + 1, poz, upd, decal);
}
A[nod + decal] = max(A[2 * nod + decal], A[2 * nod + 1 + decal]);
}
void query(int st, int dr, int nod, int a, int b, int decal)
{
if(st == dr)
{
qs = max(A[nod + decal], qs);
return;
}
int mij = st + (dr - st) / 2;
if(a <= mij)
{
query(st, mij, 2 * nod, a, b, decal);
}
if(b > mij)
{
query(mij + 1, dr, 2 * nod + 1, a, b, decal);
}
}
void dfs(int nod, int lvl)
{
u[nod] = 1;
niv[nod] = lvl;
wg[nod] = 1;
int hn = -1, frunza = 1;
for(int i = 0; i < G[nod].size(); i++)
{
int fiu = G[nod][i];
if(u[fiu] == 0)
{
dfs(fiu, lvl + 1);
frunza = 0;
wg[nod] += wg[fiu];
if(hn == -1)
{
hn = fiu;
}else
{
if(wg[fiu] > wg[hn])
{
hn = fiu;
}
}
}
}
if(frunza)
{
np++;
wp[nod] = np;
ps[np] = 1;
p[np].push_back(nod);
return;
}
wp[nod] = wp[hn];
ps[wp[nod]]++;
p[wp[nod]].push_back(nod);
for(int i = 0; i < G[nod].size(); i++)
{
int fiu = G[nod][i];
if(!(wp[fiu] == wp[nod] || niv[fiu] < niv[nod]))
{
pf[wp[fiu]] = nod;
pfniv[wp[fiu]] = niv[nod];
}
}
}
void make_paths()
{
dfs(1, 1);
for(int i = 1; i <= np; i++)
{
reverse(p[i].begin(), p[i].end());
}
for(int i = 1; i < np; i++)
{
dcj[i + 1] = dcj[i] + 4 * ps[i];
build(1, ps[i], 1, i, dcj[i]);
}
build(1, ps[np], 1, np, dcj[np]);
}
int main()
{
_cin >> n >> m;
for(int i = 1; i <= n; i++)
{
_cin >> value[i];
}
for(int i = 1; i < n; i++)
{
_cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
make_paths();
for(int i = 1; i <= m; i++)
{
_cin >> op >> x >> y;
if(op == 0)
{
update(1, ps[wp[x]], 1, niv[x] - pfniv[wp[x]], y, dcj[wp[x]]);
}else
{
sol = 0;
while(wp[x] != wp[y])
{
if(pfniv[wp[x]] < pfniv[wp[y]])
{
swap(x, y);
}
qs = 0;
query(1, ps[wp[x]], 1, 1, niv[x] - pfniv[wp[x]], dcj[wp[x]]);
sol = max(qs, sol);
x = pf[wp[x]];
}
if(niv[x] < niv[y])
{
swap(x, y);
}
qs = 0;
query(1, ps[wp[x]], 1, niv[y] - pfniv[wp[y]], niv[x] - pfniv[wp[x]], dcj[wp[x]]);
sol = max(qs, sol);
_cout << sol << "\n";
}
}
return 0;
}