///sursa folosind calea grea de descompunere...........
#include <bits/stdc++.h>
#define leftSon (node << 1)
#define rightSon ((node << 1) | 1)
using namespace std;
const int Nmax = 1e5 + 10;
const int maxlog = 17;
int n , m , i , nrc;
int v[Nmax];
int lvl[Nmax] , w[Nmax] , fa[maxlog+1][Nmax];
int lbl[Nmax] , pos[Nmax] , nod[Nmax] , len[Nmax] , up[Nmax] , add[Nmax];
int arb[Nmax<<2];
vector < int > g[Nmax];
void dfs(int node , int dad)
{
lvl[node] = lvl[dad] + 1;
w[node] = 1;
fa[0][node] = dad;
for (int i = 1; i <= maxlog; ++i)
fa[i][node] = fa[i-1][fa[i-1][node]];
for (auto &it : g[node])
{
if (it == dad) continue;
dfs(it , node);
w[node] += w[it];
}
}
void chains(int node)
{
lbl[node] = nrc;
pos[node] = ++len[nrc];
int maxx = 0, to = -1;
for (auto &it : g[node])
{
if (it == fa[0][node]) continue;
if (w[it] > maxx)
maxx = w[it], to = it;
}
if (to != -1) chains(to);
for (auto &it : g[node])
{
if (it == fa[0][node]) continue;
if (it == to) continue;
up[++nrc] = node;
chains(it);
}
}
int kanc(int x , int t)
{
for (int i = 0; i <= maxlog; ++i)
if (t & (1 << i))
x = fa[i][x];
return x;
}
int lca(int x , int y)
{
if (lvl[x] < lvl[y]) swap(x , y);
x = kanc(x , lvl[x] - lvl[y]);
if (x == y) return x;
for (int i = maxlog; i >= 0; --i)
if (fa[i][x] != fa[i][y])
x = fa[i][x] , y = fa[i][y];
return fa[0][x];
}
void build(int node , int left , int right , int k)
{
if (left == right)
{
arb[add[k]+node] = v[nod[add[k]+left]];
return;
}
int mid = (left + right) >> 1;
build(leftSon , left , mid , k);
build(rightSon , mid + 1 , right , k);
arb[add[k]+node] = max(arb[add[k]+leftSon] , arb[add[k]+rightSon]);
}
void update(int node , int left , int right , int pu , int vu , int k)
{
if (left == right)
{
arb[add[k]+node] = vu;
return;
}
int mid = (left + right) >> 1;
if (pu <= mid) update(leftSon , left , mid , pu , vu , k);
else update(rightSon , mid + 1 , right , pu , vu , k);
arb[add[k]+node] = max(arb[add[k]+leftSon] , arb[add[k]+rightSon]);
}
int query(int node , int left , int right , int lq , int rq , int k)
{
if (lq <= left && right <= rq)
return arb[add[k]+node];
int mid = (left + right) >> 1; int ret = 0;
if (lq <= mid) ret = max(ret , query(leftSon , left , mid , lq , rq , k));
if (mid < rq) ret = max(ret , query(rightSon , mid + 1 , right , lq , rq , k));
return ret;
}
int go(int x , int y)
{
if (lvl[x] < lvl[y]) return 0;
int L = (lbl[y] == lbl[x]) ? pos[y] : 1;
int R = pos[x];
int ret = query(1 , 1 , len[lbl[x]] , L , R , lbl[x]);
return max(ret , go(up[lbl[x]] , y));
}
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", v + i);
for (i = 1; i < n; ++i)
{
int x , y;
scanf("%d %d", &x, &y);
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1 , 0);
nrc = 1; chains(1);
for (i = 2; i <= nrc + 1; ++i)
add[i] = add[i-1] + (len[i-1] << 2);
for (i = 1; i <= n; ++i)
nod[add[lbl[i]]+pos[i]] = i;
for (i = 1; i <= nrc; ++i)
build(1 , 1 , len[i] , i);
for (i = 1; i <= m; ++i)
{
int op , x , y;
scanf("%d", &op);
scanf("%d %d", &x, &y);
if (op == 0)
update(1 , 1 , len[lbl[x]] , pos[x] , y , lbl[x]);
else
{
int z = lca(x , y);
int ans = max(go(x , z) , go(y , z));
printf("%d\n", ans);
}
}
return 0;
}