#include <bits/stdc++.h>
#define ll long long
#define all(a) (a).begin(), (a).end()
//#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define sz() size()
#define fr first
#define sc second
#define pb push_back
#define er erase
#define in insert
#define pi pair<int,int>
#define pii pair<pair<int,int>,int>
#define mp make_pair
//#define int long long
#define rc(s) return cout<<s,0
#define rcc(s) cout<<s,exit(0)
using namespace std;
const int mod=1e9+7;
const int modu=1999999973;
const int modul=998244353;
int n,m,val[100005],dp[100005],indx;
int pathid[100005],pathsize[100005],niv[100005],pathtata[100005];
int pathlvl[100005],tree[600005],pathdecalaj[100005];
bitset<100005>viz;
vector<int>nod[100005],path[100005];
void DFS1(int s){
int frunza = 1;
viz[s] = dp[s] = 1;
int heavyN = -1;
for(auto it:nod[s]){
if(!viz[it]){
frunza=0;
niv[it]=niv[s]+1;
DFS1(it);
dp[s]+=dp[it];
if(heavyN==-1) heavyN=it;
else{
if(dp[it]>dp[heavyN]) heavyN=it;
}
}
}
if(frunza){
pathid[s]=(++indx);
pathsize[indx]++;
path[indx].push_back(s);
return;
}
pathid[s]=pathid[heavyN];
pathsize[pathid[s]]++;
path[pathid[s]].push_back(s);
for(auto it:nod[s]){
if(it==heavyN || niv[it]<niv[s]) continue;
else{
pathtata[pathid[it]]=s;
pathlvl[pathid[it]]=niv[s];
}
}
return;
}
void build(int l,int r,int lant,int decalaj,int nod){
if(l==r){
tree[nod+decalaj] = val[path[lant][l-1]];
}
else{
int mid=l+(r-l)/2;
build(l,mid,lant,decalaj,2*nod);
build(mid+1,r,lant,decalaj,2*nod+1);
tree[nod+decalaj]=max(tree[2*nod+decalaj],tree[2*nod+1+decalaj]);
return;
}
}
void update(int l,int r,int poz,int val,int decalaj,int nod){
if(l==r){
tree[nod+decalaj]=val;
return;
}
else{
int mid=l+(r-l)/2;
if(poz<=mid) update(l,mid,poz,val,decalaj,2*nod);
else update(mid+1,r,poz,val,decalaj,2*nod+1);
tree[nod+decalaj]=max(tree[2*nod+decalaj],tree[2*nod+1+decalaj]);
return;
}
}
int query(int l,int r,int le,int re,int decalaj,int nod){
if(l>re || r<le) return 0;
else if(l>=le && r<=re) return tree[nod+decalaj];
else{
int mid=l+(r-l)/2;
return max(query(l,mid,le,re,decalaj,2*nod),query(mid+1,r,le,re,decalaj,2*nod+1));
}
}
int32_t main(){
ios_base::sync_with_stdio(false);cin.tie(0);cerr.tie(0);cout.tie(0);
srand(chrono::steady_clock::now().time_since_epoch().count());
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> val[i];
for(int i=1;i<n;i++){
int x,y;
cin >> x >> y;
nod[x].push_back(y);
nod[y].push_back(x);
}
niv[1]=1;
DFS1(1);
for(int i=1;i<=indx;i++) reverse(all(path[i]));
for(int i=1;i<=indx;i++){
if(i>1) pathdecalaj[i]=pathdecalaj[i-1]+4*pathsize[i-1];
build(1,pathsize[i],i,pathdecalaj[i],1);
}
for(int i=1;i<=m;i++){
int t,x,y ;
cin >> t >> x >> y;
if(t==0){
update(1,pathsize[pathid[x]],niv[x]-pathlvl[pathid[x]],y,pathdecalaj[pathid[x]],1);
}
else{
int ans=0;
while(true){
if(pathid[x]==pathid[y]){
if(niv[x]>niv[y]) swap(x,y);
ans=max(ans,query(1,pathsize[pathid[x]],niv[x]-pathlvl[pathid[x]],niv[y]-pathlvl[pathid[y]],pathdecalaj[pathid[x]],1));
break;
}
else{
if(pathlvl[pathid[x]]<pathlvl[pathid[y]]) swap(x,y);
ans=max(ans,query(1,pathsize[pathid[x]],1,niv[x]-pathlvl[pathid[x]],pathdecalaj[pathid[x]],1));
x=pathtata[pathid[x]];
}
}
cout << ans << '\n';
}
}
}