#include<cstdio>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<bitset>
#include<deque>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<unordered_map>
#define ll long long
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
using namespace std;
const int nmax = 100005;
int n, m, i, x, y, paths, poz, val, op, a, b, sol;
int lev[nmax], f[nmax], cost[nmax], sub[nmax];
int sz[nmax], lant[nmax], where[nmax];
vector<int> v[nmax], p[nmax], seg[nmax];
void dfs(int x, int d)
{
sub[x] = 1;
for(auto it : v[x])
if(it != d)
{
lev[it] = lev[x] + 1;
f[it] = x;
dfs(it, x);
sub[x] += sub[it];
}
if(v[x].size() == 1 && x != 1)
{
lant[x] = ++paths;
p[paths].pb(0);
p[paths].pb(x);
where[x] = ++sz[paths];
return;
}
int maxi = 0;
for(auto it : v[x])
if(it != d && sub[it] > sub[maxi])
maxi = it;
lant[x] = lant[maxi];
p[lant[x]].pb(x);
where[x] = ++sz[lant[x]];
}
void build(int node, int l, int r, int path)
{
if(l == r)
{
seg[path][node] = cost[p[path][l]];
return;
}
int mi = (l + r) / 2;
int ls = 2 * node;
int rs = 2 * node + 1;
build(ls, l, mi, path);
build(rs, mi + 1, r, path);
seg[path][node] = max(seg[path][ls], seg[path][rs]);
}
void update(int node, int l, int r, int poz, int val, int path)
{
if(l == r)
{
seg[path][node] = val;
return;
}
int mi = (l + r) / 2;
int ls = 2 * node;
int rs = 2 * node + 1;
if(poz <= mi)
update(ls, l, mi, poz, val, path);
else
update(rs, mi + 1, r, poz, val, path);
seg[path][node] = max(seg[path][ls], seg[path][rs]);
}
void query(int node, int l, int r, int a, int b, int path)
{
if(l >= a && r <= b)
{
sol = max(sol, seg[path][node]);
return;
}
int mi = (l + r) / 2;
int ls = 2 * node;
int rs = 2 * node + 1;
if(a <= mi)
query(ls, l, mi, a, b, path);
if(b > mi)
query(rs, mi + 1, r, a, b, path);
}
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d%d", &n, &m);
for(i = 1; i <= n; i++)
scanf("%d", &cost[i]);
for(i = 1; i < n; i++)
{
scanf("%d%d", &x, &y);
v[x].pb(y);
v[y].pb(x);
}
dfs(1, 0);
for(i = 1; i <= paths; i++)
{
reverse(p[i].begin() + 1, p[i].end());
seg[i].resize(4 * sz[i] + 5);
build(1, 1, sz[i], i);
}
for(i = 1; i <= n; i++)
where[i] = sz[lant[i]] + 1 - where[i];
for(; m; m--)
{
scanf("%d", &op);
if(op == 0)
{
scanf("%d%d", &x, &val);
poz = where[x];
update(1, 1, sz[lant[x]], poz, val, lant[x]);
}
else
{
scanf("%d%d", &x, &y);
sol = 0;
for(;;)
{
if(lant[x] == lant[y])
{
a = min(where[x], where[y]);
b = max(where[x], where[y]);
query(1, 1, sz[lant[x]], a, b, lant[x]);
break;
}
if(lev[p[lant[x]][1]] < lev[p[lant[y]][1]])
swap(x, y);
a = 1;
b = where[x];
query(1, 1, sz[lant[x]], a, b, lant[x]);
x = f[p[lant[x]][1]];
}
printf("%d\n", sol);
}
}
return 0;
}