#include <fstream>
#include <vector>
#include <algorithm>
#define maxn 100001
#define vint vector<int>::iterator
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
int n,m;
int v[maxn],wh[maxn];
vector<int> T[maxn];
vector<int> P[maxn];
int arb[4*maxn],arbpos[maxn],parent[maxn],depth[maxn];
int l,r,ans,jump,total,val,a,b,t,x,y;
int dfs (int x, int father, int lvl)
{
depth[x] = lvl;
bool leaf = 1;
int sum = 0, heavy = 0, heavysize= 0;
for (vint it = T[x].begin (); it != T[x].end(); ++it )
{
if (*it != father)
{
leaf = 0;
int childsize = dfs (*it,x,lvl+1);
if (childsize > heavysize)
{
heavy = *it;
heavysize = childsize;
}
sum += childsize;
}
}
if (leaf)
{
++total;
P[total].push_back (x);
wh[x] = total;
}
else
{
P[wh[heavy]].push_back (x);
wh[x] = wh[heavy];
for (vint it = T[x].begin (); it != T[x].end(); ++it)
{
if (*it != father && *it != heavy)
{
parent[wh[*it]] = x;
}
}
}
return sum+1;
}
void make_tree (int node, int left, int right)
{
if (left == right)
{
arb[node+jump] = v[P[l][left-1]];
return;
}
int mid = (left + right)/2;
make_tree (node<<1,left,mid);
make_tree ((node<<1)+1,mid+1,right);
arb[node+jump] = max(arb[(node<<1)+jump],arb[(node<<1)+1+jump]);
}
void build_trees ()
{
jump = 0;
for (int i = 1; i<=total; ++i)
{
l=i;
reverse (P[i].begin(),P[i].end());
make_tree (1,1,P[i].size());
arbpos[i] = jump;
jump += 4*P[i].size();
}
}
void update (int node, int left, int right)
{
if (left == right)
{
arb[node+jump] = val;
return;
}
int mid = (left + right)/2;
if (l <= mid)
update (node<<1,left,mid);
else update ((node<<1)+1,mid+1,right);
arb[node+jump] = max (arb[(node<<1)+jump],arb[(node<<1)+1+jump]);
}
void query (int node, int left, int right)
{
if (l <= left && right <= r)
{
ans = max (ans,arb[node+jump]);
return;
}
int mid = (left + right)/2;
if (l <= mid)
query (node<<1,left,mid);
if (r > mid)
query ((node<<1)+1,mid+1,right);
}
int main()
{
fin>>n>>m;
for (int i=1; i<=n; ++i)
fin>>v[i];
for (int i=1; i<n; ++i)
{
fin>>a>>b;
T[a].push_back (b);
T[b].push_back (a);
}
dfs (1,0,1);
build_trees ();
for (int i=1; i<=m; ++i)
{
fin>>t;
if (!t)
{
fin>>x>>val;
jump = arbpos[wh[x]];
l = depth[x] - depth[parent[wh[x]]];
update (1,1,P[wh[x]].size());
}
else
{
fin>>x>>y;
ans = 0;
while (wh[x] != wh[y])
{
if (depth[x] < depth[y])
swap (x,y);
l = 1;
r = depth[x] - depth[parent[wh[x]]];
jump = arbpos[wh[x]];
query (1,1,P[wh[x]].size());
x = parent[wh[x]];
}
l = depth[x] - depth[parent[wh[x]]];
r = depth[y] - depth[parent[wh[y]]];
if (l > r)
swap (l,r);
jump = arbpos[wh[x]];
query (1,1,P[wh[x]].size());
fout<<ans<<"\n";
}
}
}