#include <bits/stdc++.h> //Andrei Alexandru a.k.a Sho
#define ll long long
#define double long double
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#define aint(a) (a).begin(), (a).end()
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define pi pair
#define rc(s) return cout<<s,0
#define endl '\n'
#define mod 1000000007
#define PI 3.14159265359
#define INF 1000000005
#define LINF 1000000000000000005ll
#define CODE_START ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
ll n,q,a[200005],pos[200005],depth[200005],roof[200005],sub[200005],c[200005],col=1,sz[200005],tin[200005],tout[200005],timer=0;
vector<ll>g[200005];
vector<ll>tree[200005];
void dfs1(ll node,ll par){
ll check=1;
sub[node]=1;
tin[node]=++timer;
ll heavy=-1;
for(auto it : g[node]){
if(it!=par){
check=0;
depth[it]=depth[node]+1;
dfs1(it,node);
sub[node]+=sub[it];
}
}
tout[node]=++timer;
}
void dfs(ll node,ll par){
ll heavy=-1;
for(auto it : g[node]){
if(it!=par){
if(heavy==-1){
heavy=it;
}else if(sub[it]>sub[heavy]){
heavy=it;
}
}
}
if(heavy==-1){
return;
}
for(auto it : g[node]){
if(it!=par){
if(it==heavy){
c[it]=c[node];
pos[it]=pos[node]+1;
sz[c[it]]=max(sz[c[it]],pos[it]);
dfs(it,node);
}else {
c[it]=++col;
roof[c[it]]=node;
pos[it]=1;
sz[c[it]]=1;
dfs(it,node);
}
}
}
}
void update(ll indx,ll node,ll l,ll r,ll poss,ll val){
if(l>poss){
return;
}
if(r<poss){
return;
}
if(l==r){
tree[indx][node]=val;
return;
}
ll mid=(l+r)/2;
update(indx,2*node,l,mid,poss,val);
update(indx,2*node+1,mid+1,r,poss,val);
tree[indx][node]=max(tree[indx][node*2],tree[indx][2*node+1]);
}
ll query(ll indx,ll node,ll l,ll r,ll st,ll dr){
if(r<st){
return 0;
}
if(l>dr){
return 0;
}
if(st<=l&&r<=dr){
return tree[indx][node];
}
ll mid=(l+r)/2;
return max(query(indx,2*node,l,mid,st,dr),query(indx,2*node+1,mid+1,r,st,dr));
}
bool check(ll x,ll y){
return tin[x]<=tin[y] && tout[x]>=tout[y];
}
int32_t main(){
CODE_START;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin>>n>>q;
c[1]=1;
pos[1]=1;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
}
for(ll i=1;i<n;i++)
{
ll l,r;
cin>>l>>r;
g[l].pb(r);
g[r].pb(l);
}
dfs1(1,0);
dfs(1,0);
for(ll i=1;i<=col;i++)
{
for(ll j=0;j<=100*sz[i];j++)
{
tree[i].pb(0);
}
}
for(ll i=1;i<=n;i++)
{
// cout<<c[i]<<' '<<pos[i]<<' '<<roof[c[i]]<<endl;
update(c[i],1,1,sz[c[i]],pos[i],a[i]);
}
while(q--){
ll type;
cin>>type;
if(type==1){
ll poss,val;
cin>>poss>>val;
update(c[poss],1,1,sz[c[poss]],pos[poss],val);
}else {
ll x=1,y,yy;
cin>>y>>yy;
ll ans=0;
if(check(y,yy)==0&&check(yy,y)==0){
ll res=0;
while(1){
if(y==0){
break;
}
if(c[x]==c[y]){
ans=max(ans,query(c[x],1,1,sz[c[x]],pos[x],pos[y]));
}else {
ans=max(ans,query(c[y],1,1,sz[c[y]],1,pos[y]));
}
if(c[x]==c[y]){
break;
}else {
y=roof[c[y]];
}
}
x=1;
y=yy;
while(1){
if(y==0){
break;
}
if(c[x]==c[y]){
ans=max(ans,query(c[x],1,1,sz[c[x]],pos[x],pos[y]));
}else {
ans=max(ans,query(c[y],1,1,sz[c[y]],1,pos[y]));
}
if(c[x]==c[y]){
break;
}else {
y=roof[c[y]];
}
}
}else {
if(check(y,yy)==0){
swap(y,yy);
}
x=y;
y=yy;
while(1){
if(y==0){
break;
}
if(c[x]==c[y]){
ans=max(ans,query(c[x],1,1,sz[c[x]],pos[x],pos[y]));
}else {
ans=max(ans,query(c[y],1,1,sz[c[y]],1,pos[y]));
}
if(c[x]==c[y]){
break;
}else {
y=roof[c[y]];
}
}
}
cout<<ans<<' ';
}
}
}
/*
10 10
5 4 1 9 5 3 1 2 9 8
10 4
10 3
6 2
2 5
9 5
5 8
7 4
7 6
1 6
2 9
1 10 5
2 8
2 5
2 8
2 3
1 7 5
2 2
2 5
1 6 2
*/