#include <bits/stdc++.h>
#pragma GCC optimize ("03")
#define FastIO ios_base::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
#define FILES freopen("heavypath.in" , "r" , stdin) , freopen("heavypath.out" , "w" , stdout)
#define pb push_back
using namespace std;
const int N = 1e5 + 10;
int n , m , op , x , y;
int pos_chain[N] , height[N] , leaf[N] , parent[N] , nr[N] , a[N];
vector < int > g[N] , chain[N];
struct aib
{
aib *l , *r;
int maxi;
aib()
{
l = r = 0;
maxi = 0;
}
}*T[N];
int chains = 0;
void dfs(int node)
{
nr[node] = 1;
int w = -1;
for(int i = 0 ; i < g[node].size() ; i++)
if(!height[ g[node][i] ])
{
height[ g[node][i] ] = height[node] + 1;
parent[ g[node][i] ] = node;
dfs( g[node][i] );
nr[node] += nr[ g[node][i] ];
if(w == -1 || nr[w] < nr[ g[node][i] ])
w = g[node][i];
}
if(w == -1)
{
++chains;
chain[chains].pb(node);
leaf[node] = chains;
pos_chain[node] = 0;
return;
}
chain[ leaf[w] ].pb(node);
pos_chain[node] = chain[ leaf[w] ].size() - 1;
leaf[node] = leaf[w];
}
int mx(aib *root)
{
if(root == 0) return 0;
else return root -> maxi;
}
void update(int l , int r , int pos , int val , aib *&root)
{
if(l == r)
{
root -> maxi = val;
return;
}
int mid = (l + r) / 2;
if(pos <= mid)
{
if(root -> l == 0) root -> l = new aib;
update(l , mid , pos , val , root -> l);
}
else
{
if(root -> r == 0) root -> r = new aib;
update(mid + 1 , r , pos , val , root -> r);
}
root -> maxi = max(mx(root -> l) , mx(root -> r));
}
void query(int l , int r , int ql , int qr , aib *root , int &ans)
{
if(root == 0)
return;
if(ql <= l && r <= qr)
return ans = max(ans , root -> maxi) , void();
int mid = (r + l) / 2;
if(ql <= mid) query(l , mid , ql , qr , root -> l , ans);
if(mid < qr) query(mid + 1 , r , ql , qr , root -> r , ans);
}
void build_aib()
{
height[1] = 1;
for(int i = 1 ; i <= chains ; i++)
{
T[i] = new aib;
for(auto j : chain[i])
update(0 , chain[i].size() - 1 , pos_chain[j] , a[j] , T[i]);
}
}
signed main()
{
#ifndef ONLINE_JUDGE
FastIO , FILES;
#endif
int i;
cin >> n >> m;
for(i = 1 ; i <= n ; i++)
cin >> a[i];
for(i = 1 ; i < n ; i++)
{
cin >> x >> y;
g[x].pb(y);
g[y].pb(x);
}
dfs(1);
build_aib();
chain[0].pb(1);
for(i = 1 ; i <= m ; i++)
{
cin >> op >> x >> y;
if(op == 0)
{
int ch = leaf[x];
update(0 , chain[ch].size() - 1 , pos_chain[x] , y , T[ch]);
}
else
{
int ans = 0;
while(leaf[x] != leaf[y])
{
int p_chain_x = parent[ chain[ leaf[x] ].back() ];
int p_chain_y = parent[ chain[ leaf[y] ].back() ];
if(height[ p_chain_x ] < height[ p_chain_y ])
swap(x , y) , swap(p_chain_x , p_chain_y);
query(0 , chain[ leaf[x] ].size() - 1 , pos_chain[x] , chain[ leaf[x] ].size() - 1 , T[ leaf[x] ] , ans);
x = p_chain_x;
}
query(0 , chain[ leaf[x] ].size() - 1 , min(pos_chain[x] , pos_chain[y]) , max(pos_chain[x] , pos_chain[y]) , T[ leaf[x] ] , ans);
cout << ans << '\n';
}
}
return 0;
}