#include <bits/stdc++.h>
#define maxN 100002
#define inf 0x3fffffff
using namespace std;
FILE *fin = freopen("heavypath.in", "r", stdin);
FILE *fout = freopen("heavypath.out", "w", stdout);
int n, m;
int v[maxN];
int nrCh, sub[maxN], lev[maxN], pos[maxN], head[maxN];
vector < int > V[maxN], Chain[maxN];
int ChainId[maxN];
int ans;
class st
{
public :
vector < int > aint;
inline void update(int node, int l, int r, int p, int val)
{
if (l > r)
return;
if (l == r)
{
aint[node] = val;
return ;
}
int lson = 2 * node, rson = lson + 1, mid = (l + r) >> 1;
if (p <= mid)
update(lson, l, mid, p, val);
else
update(rson, mid + 1, r, p, val);
aint[node] = max(aint[lson], aint[rson]);
}
inline int query(int node, int l, int r, int x, int y)
{
if (l > r)
return -inf;
if (l == x && r == y)
return aint[node];
int lson = 2 * node, rson = lson + 1, mid = (l + r) >> 1;
if (y <= mid)
return query(lson, l, mid, x, y);
else
{
if (x > mid)
return query(rson, mid + 1, r, x, y);
else
return max(query(lson, l, mid, x, mid), query(rson, mid + 1, r, mid + 1, y));
}
}
} trees[maxN];
void dfs(int x)
{
int spSon = -1;
sub[x] = 1;
for (int y : V[x])
if (!sub[y])
{
dfs(y);
lev[y] = lev[x] + 1;
sub[x] += sub[y];
if (spSon == -1 || sub[spSon] < sub[y])
spSon = y;
head[ChainId[y]] = x;
}
if (spSon == -1)
{
++ nrCh;
pos[x] = 1;
ChainId[x] = nrCh;
Chain[nrCh].push_back(x);
}
else
{
ChainId[x] = ChainId[spSon];
head[ChainId[x]] = 0;
pos[x] = pos[spSon] + 1;
Chain[ChainId[x]].push_back(x);
}
}
void compAint()
{
for (int i = 1; i <= nrCh; ++ i)
{
trees[i].aint.resize(Chain[i].size() * 4);
for (int j = 0; j < Chain[i].size(); ++ j)
trees[i].update(1, 1, Chain[i].size(), j + 1, v[Chain[i][j]]);
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++ i)
scanf("%d", &v[i]);
for (int i = 0; i < n - 1; ++ i)
{
int x, y;
scanf("%d%d", &x, &y);
V[x].push_back(y);
V[y].push_back(x);
}
dfs(1);
compAint();
for (int x = 1; x <= n; ++ x)
trees[ChainId[x]].update(1, 1, Chain[ChainId[x]].size(), pos[x], v[x]);
while (m --)
{
int ty, x, y;
scanf("%d%d%d", &ty, &x, &y);
if (!ty)
trees[ChainId[x]].update(1, 1, Chain[ChainId[x]].size(), pos[x], y);
else
{
ans = -inf;
while (ChainId[x] != ChainId[y])
{
if (lev[head[ChainId[x]]] < lev[head[ChainId[y]]])
swap(x, y);
ans = max(ans, trees[ChainId[x]].query(1, 1, Chain[ChainId[x]].size(), pos[x], Chain[ChainId[x]].size()));
x = head[ChainId[x]];
}
if (pos[x] > pos[y]) swap(x, y);
ans = max(ans, trees[ChainId[x]].query(1, 1, Chain[ChainId[x]].size(), pos[x], pos[y]));
printf("%d\n", ans);
}
}
return 0;
}