#include <bits/stdc++.h>
#define leftSon (node << 1)
#define rightSon ((node << 1) | 1)
using namespace std;
const int Nmax = 1e5 + 10;
int n , m , i , nrc;
int v[Nmax];
int w[Nmax] , lvl[Nmax] , fa[Nmax];
int whr[Nmax] , pos[Nmax] , len[Nmax];
int *arb[Nmax];
vector < int > lbl[Nmax];
vector < int > g[Nmax];
void dfs(int node)
{
w[node] = 1; lvl[node] = lvl[fa[node]] + 1;
for (auto &it : g[node])
{
if (it == fa[node]) continue;
fa[it] = node;
dfs(it);
w[node] += w[it];
}
}
void chains(int node)
{
whr[node] = nrc;
lbl[nrc].push_back(node);
pos[node] = (int)lbl[nrc].size();
int maxx = 0, to = -1;
for (auto &it : g[node])
{
if (it == fa[node]) continue;
if (w[it] > maxx)
maxx = w[it], to = it;
}
if (to != -1) chains(to);
for (auto &it : g[node])
{
if (it == fa[node]) continue;
if (it == to) continue;
nrc++;
chains(it);
}
}
void build(int node , int left , int right , int ind)
{
if (left == right)
{
arb[ind][node] = v[lbl[ind][left-1]];
return;
}
int mid = (left + right) >> 1;
build(leftSon , left , mid , ind);
build(rightSon , mid + 1 , right , ind);
arb[ind][node] = max(arb[ind][leftSon] , arb[ind][rightSon]);
}
void update(int node , int left , int right , int pu , int vu , int ind)
{
if (left == right)
{
arb[ind][node] = vu;
return;
}
int mid = (left + right) >> 1;
if (pu <= mid) update(leftSon , left , mid , pu , vu , ind);
else update(rightSon , mid + 1 , right , pu , vu , ind);
arb[ind][node] = max(arb[ind][leftSon] , arb[ind][rightSon]);
}
int query(int node , int left , int right , int lq , int rq , int ind)
{
if (lq <= left && right <= rq)
return arb[ind][node];
int mid = (left + right) >> 1; int ret = 0;
if (lq <= mid) ret = max(ret , query(leftSon , left , mid , lq , rq , ind));
if (mid < rq) ret = max(ret , query(rightSon , mid + 1 , right , lq , rq , ind));
return ret;
}
int go(int x , int y)
{
if (whr[x] == whr[y])
{
if (pos[x] > pos[y]) swap(x , y);
return query(1 , 1 , len[whr[x]] , pos[x] , pos[y] , whr[x]);
}
int dadx = lbl[whr[x]][0]; int dady = lbl[whr[y]][0];
if (lvl[dadx] < lvl[dady])
swap(x , y);
int ret = query(1 , 1 , len[whr[x]] , 1 , pos[x] , whr[x]);
return max(ret , go(fa[lbl[whr[x]][0]] , 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);
nrc = 1; chains(1);
for (i = 1; i <= nrc; ++i)
{
len[i] = (int)lbl[i].size();
arb[i] = new int [len[i]<<2];
build(1 , 1 , len[i] , i);
}
for (i = 1; i <= m; ++i)
{
int op , x , y;
scanf("%d %d %d", &op, &x, &y);
if (op == 0) update(1 , 1 , len[whr[x]] , pos[x] , y , whr[x]);
else printf("%d\n", go(x , y));
}
return 0;
}