#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>
using namespace std;
const int nmax = 100005;
int n, m, i, x, y, paths, Poz, Val, a, b, sol;
int val[nmax], subarb[nmax], lev[nmax];
int f[nmax], poz[nmax], lant[nmax];
vector<int> v[nmax], p[nmax], arb[nmax];
void dfs(int x, int t)
{
subarb[x] = 1;
for(auto it : v[x])
if(it != t)
{
f[it] = x;
lev[it] = lev[x] + 1;
dfs(it, x);
subarb[x] += subarb[it];
}
if(v[x].size() == 1 && x != 1)
{
lant[x] = ++paths;
p[paths].push_back(0);
p[paths].push_back(x);
poz[x] = 1;
return;
}
int maxs = 0;
for(auto it : v[x])
if(it != t && subarb[it] > subarb[maxs])
maxs = it;
lant[x] = lant[maxs];
p[lant[x]].push_back(x);
poz[x] = p[lant[x]].size() - 1;
}
void build(int node, int l, int r, int path)
{
if(l == r)
{
arb[path][node] = val[p[path][l]];
return;
}
int m = (l + r) / 2;
int ls = 2 * node;
int rs = ls + 1;
build(ls, l, m, path);
build(rs, m + 1, r, path);
arb[path][node] = max(arb[path][ls], arb[path][rs]);
}
void update(int node, int l, int r, int path)
{
if(l == r)
{
arb[path][node] = Val;
return;
}
int m = (l + r) / 2;
int ls = 2 * node;
int rs = ls + 1;
if(Poz <= m) update(ls, l, m, path);
else update(rs, m + 1, r, path);
arb[path][node] = max(arb[path][ls], arb[path][rs]);
}
void query(int node, int l, int r, int path)
{
if(l >= a && r <= b)
{
sol = max(sol, arb[path][node]);
return;
}
int m = (l + r) / 2;
int ls = 2 * node;
int rs = ls + 1;
if(a <= m) query(ls, l, m, path);
if(b > m) query(rs, m + 1, r, 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", &val[i]);
for(i = 1; i < n; i++)
{
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
}
lev[1] = 1;
dfs(1, 0);
for(i = 1; i <= paths; i++)
{
reverse(p[i].begin() + 1, p[i].end());
arb[i].resize(4 * p[i].size() + 5);
build(1, 1, p[i].size() - 1, i);
}
for(i = 1; i <= n; i++)
poz[i] = p[lant[i]].size() - poz[i];
for(; m; m--)
{
scanf("%d%d%d", &i, &x, &y);
if(i == 0)
{
Poz = poz[x];
Val = y;
update(1, 1, p[lant[x]].size() - 1, lant[x]);
}
else
{
sol = 0;
for(;;)
{
if(lant[x] == lant[y])
{
a = min(poz[x], poz[y]);
b = max(poz[x], poz[y]);
query(1, 1, p[lant[x]].size() - 1, lant[x]);
break;
}
if(lev[p[lant[x]][1]] < lev[p[lant[y]][1]])
swap(x, y);
a = 1;
b = poz[x];
query(1, 1, p[lant[x]].size() - 1, lant[x]);
x = f[p[lant[x]][1]];
}
printf("%d\n", sol);
}
}
return 0;
}