#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 ll long long
#define ull unsigned long long
#define ld long double
#define eb emplace_back
#define pb push_back
#define qwerty1 first
#define qwerty2 second
#define qwerty3 -> first
#define qwerty4 -> second
#define umap unordered_map
#define uset unordered_set
#define pii pair < int , int >
#define pq priority_queue
#define dbg(x) cerr << #x << ": " << x << '\n'
namespace FastRead
{
char buff[5000];int lg = 0 , p = 0;
char nc()
{
if(lg == p){lg = fread(buff , 1 , 5000 , stdin);p = 0;if(!lg) return EOF;}
return buff[p++];
}
template<class T>void read(T&x)
{
T sgn = 1; char c;while(!isdigit(c = nc()))if(c == '-')sgn = -1;
x = c - '0';while(isdigit(c = nc()))x = x * 10 + c - '0';x *= sgn;
}
}
using namespace FastRead;
using namespace std;
const int N = 1e5 + 10;
const int M = 1e9 + 7;
const ld PI = acos(-1);
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
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 , int h , int p)
{
height[node] = h;
parent[node] = p;
nr[node] = 1;
if(g[node].size() == 1 && node != 1)
{
++chains;
chain[chains].pb(node);
leaf[node] = chains;
pos_chain[node] = 0;
return;
}
int w = -1;
for(auto i : g[node])
if(i != p)
{
dfs(i , h + 1 , node);
nr[node] += nr[i];
if(w == -1 || nr[w] < nr[i])
w = i;
}
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()
{
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 , 0 , 0);
build_aib();
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;
}