#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int nmax = 100000 + 10;
const int LOG = 17;
int pa[LOG + 1][nmax];
int tmp[nmax] , w[nmax] , d[nmax] , len[nmax] , lbl[nmax] , whr[nmax] , up[nmax] , aint[3 * nmax] , add[nmax];
vector < int > g[nmax];
int n , q , x , y , type , nrc , i , res , j , z;
void DP()
{
for (int i = 1 ; i <= LOG ; ++i)
for (int j = 1 ; j <= n ; ++j)
pa[i][j] = pa[i - 1][pa[i - 1][j]];
}
int kanc(int n , int k)
{
for (int i = LOG ; i >= 0 ; --i)
if ( (1 << i) <= k)
{
k -= (1 << i);
n = pa[i][n];
}
return n;
}
int lca(int x , int y)
{
// x is deeper than y
if (d[x] < d[y]) swap(x , y);
int q = d[x] - d[y];
x = kanc(x , q);
if (x == y) return x;
//now x is at same level with y
for (int i = LOG ; i >= 0 ; --i)
if (pa[i][x] != pa[i][y])
{
x = pa[i][x];
y = pa[i][y];
}
return pa[0][x];
}
void df(int x , int fa)
{
w[x] = 1;
d[x] = d[fa] + 1;
pa[0][x] = fa;
for (auto j = g[x].begin() ; j != g[x].end() ; ++j)
{
int y = *j;
if (y == fa) continue;
df(y , x);
w[x] += w[y];
}
}
void doChains(int x)
{
int to = 0;
len[nrc] += 1;
lbl[x] = nrc , whr[x] = len[nrc];
for (auto j = g[x].begin() ; j != g[x].end() ; ++j)
{
int y = *j;
if (y == pa[0][x]) continue;
if (w[*j] > w[to]) to = *j;
}
if (to)
doChains(to);
else ++nrc;
for (auto j = g[x].begin() ; j != g[x].end() ; ++j)
{
int y = *j;
if (y == pa[0][x] || y == to) continue;
up[nrc] = x;
doChains(y);
}
}
void change(int k , int x , int l , int r , int p , int y , int add)
{
if (l == r)
{
aint[add + x] = y;
return ;
}
int m = (l + r) >> 1;
if (p <= m)
change(k , 2 * x , l , m , p , y , add);
else change(k , 2 * x + 1 , m + 1 , r , p , y , add);
aint[add + x] = max(aint[add + 2 * x] , aint[add + 2 * x + 1]);
}
void query(int k , int x , int l , int r , int lq , int rq , int add)
{
if (lq <= l && r <= rq)
{
res = max(res , aint[add + x]);
return ;
}
int m = (l + r) >> 1;
if (m >= lq)
query(k , 2 * x , l , m , lq , rq , add);
if (m < rq)
query(k , 2 * x + 1 , m + 1 , r , lq , rq , add);
}
void go(int x , int z)
{
int j = lbl[x];
int from = whr[x];
int to;
if (lbl[z] == j)
to = whr[z];
else to = 1;
query(j , 1 , 1 , len[j] , to , from , add[j]);
if (lbl[x] == lbl[y]) return ;
go(up[j] , z);
}
int main()
{
fin >> n >> q;
for (i = 1 ; i <= n ; ++i)
fin >> tmp[i];
for (i = 1 ; i < n ; ++i)
{
fin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
df(1 , 0);
DP();
nrc = 1;
doChains(1);
nrc -= 1;
add[1] = 0;
for (i = 2 ; i <= nrc ; ++i)
add[i] = add[i - 1] + 3 * len[i - 1];
for (i = 1 ; i <= n ; ++i)
{
j = lbl[i];
change(j , 1 , 1 , len[j] , whr[i] , tmp[i] , add[j]);
}
for (i = 1 ; i <= q ; ++i)
{
fin >> type >> x >> y;
if (type == 0)
{
j = lbl[x];
change(j , 1 , 1 , len[j] , whr[x] , y , add[j]);
}
else
{
z = lca(x , y);
res = 0;
go(x , z);
go(y , z);
fout << res << '\n';
}
}
return 0;
}