#include <fstream>
#include <vector>
using namespace std;
ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");
#define pb push_back
#define ll int
const int NMAX = 100005;
const int N2 = 20;
vector <int> g[NMAX];
ll seg[4 * NMAX];
ll sz[NMAX];
ll heavy_child[NMAX];
ll label[NMAX];
ll depth[NMAX];
ll chain[NMAX];
ll a[NMAX];
ll dad[NMAX];
ll n;
ll combine(ll a, ll b)
{
return max(a, b);
}
void update(int nod, int l, int r, int poz, int val)
{
if (l == r)
{
seg[nod] = val;
return;
}
int mid = (l + r) / 2, ls = 2 * nod, rs = ls + 1;
if (poz <= mid)
update(ls, l, mid, poz, val);
else
update(rs, mid + 1, r, poz, val);
seg[nod] = combine(seg[ls], seg[rs]);
}
ll query(int nod, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
return seg[nod];
if (l > r || r < ql || qr < l)
return 0;
int mid = (l + r) / 2, ls = 2 * nod, rs = ls + 1;
ll a = query(ls, l, mid, ql, qr);
ll b = query(rs, mid + 1, r, ql, qr);
return combine(a, b);
}
void subarb(int nod)
{
sz[nod] = 1;
int maxi = -1;
for (int i = 0; i < g[nod].size(); i++)
{
int x = g[nod][i];
if (dad[x])
continue;
dad[x] = nod;
depth[x] = depth[nod] + 1;
subarb(x);
sz[nod] += sz[x];
if (maxi == -1)
maxi = x;
else
if (sz[x] > sz[maxi])
maxi = x;
}
heavy_child[nod] = maxi;
}
void compute_chains(int nod)
{
if (heavy_child[nod] != -1)
chain[heavy_child[nod]] = chain[nod];
for (int i = 0; i < g[nod].size(); i++)
{
int x = g[nod][i];
if (x != dad[nod])
compute_chains(x);
}
}
int timp = 0;
void compute_labels(int nod)
{
label[nod] = ++timp;
update(1, 1, n, timp, a[nod]);
if (heavy_child[nod] != -1)
compute_labels(heavy_child[nod]);
for (int i = 0; i < g[nod].size(); i++)
{
int x = g[nod][i];
if (x != dad[nod] && x != heavy_child[nod])
compute_labels(x);
}
}
ll p2[N2];
int main()
{
int i, q;
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> q;
for (i = 1; i <= n; i++)
{
cin >> a[i];
chain[i] = i;
}
for (i = 1; i < n; i++)
{
int x, y;
cin >> x >> y;
g[x].pb(y);
g[y].pb(x);
}
dad[1] = -1;
depth[1] = 1;
subarb(1);
compute_chains(1);
compute_labels(1);
p2[0] = 1;
for (i = 1; i < N2; i++)
p2[i] = 2 * p2[i - 1];
while (q--)
{
int tip, x, y;
cin >> tip;
tip++;
if (tip == 1)
{
cin >> x >> y;
update(1, 1, n, label[x], y);
continue;
}
cin >> x>> y;
int ans = 0;
while (chain[x] != chain[y])
{
if (depth[chain[x]] < depth[chain[y]])
swap(x, y);
ans = max(ans, query(1, 1, n, label[chain[x]], label[x]));
x = dad[chain[x]];
}
if (depth[x] > depth[y])
swap(x, y);
cout << combine(ans, query(1, 1, n, label[x], label[y])) <<'\n';
}
return 0;
}