#include<bits/stdc++.h>
using namespace std;
#define MAXN (int)1e5
int dep[MAXN+1],pr[MAXN+1],sz[MAXN+1],pos[MAXN+1],c[MAXN+1],head[MAXN+1];
vector<int>adj[MAXN+1];
void dfs(int u,int fa) {
dep[u]=1+dep[fa];
pr[u]=fa;
sz[u]=1;
for(auto v:adj[u]) {
if(v!=fa) {
dfs(v,u);
sz[u]+=sz[v];
}
}
}
int ind=0,tim=0;
void heavy_dfs(int u,int fa,int idx) {
pos[u]=++tim;
c[u]=ind;
for(auto v:adj[u]) {
if(v!=fa) {
if(sz[v]>sz[u]/2) {
heavy_dfs(v,u,idx);
}
}
}
for(auto v:adj[u]) {
if(v!=fa) {
if(sz[v]<=sz[u]/2) {
ind++;
head[ind]=v;
heavy_dfs(v,u,ind);
}
}
}
}
int aint[MAXN*4+1];
int val[MAXN+1];
void update(int nd,int tl,int tr,int pos,int val) {
if(tr<pos||tl>pos) {
return;
}
if(tl==tr) {
aint[nd]=val;
return;
}
int tm=(tl+tr)/2;
update(nd*2,tl,tm,pos,val);
update(nd*2+1,tm+1,tr,pos,val);
aint[nd]=max(aint[nd*2],aint[nd*2+1]);
}
int query(int nd,int tl,int tr,int a,int b) {
if(tr<a||tl>b) {
return 0;
}
if(a<=tl&&tr<=b) {
return aint[nd];
}
int tm=(tl+tr)/2;
int v1=query(nd*2,tl,tm,a,b);
int v2=query(nd*2+1,tm+1,tr,a,b);
return max(v1,v2);
}
int n;
int solve(int a,int b) {
int ans=0;
while(c[a]!=c[b]) {
if(dep[head[c[a]]]<dep[head[c[b]]]) {
swap(a,b);
}
ans=max(ans,query(1,1,n,pos[head[c[a]]],pos[a]));
a=pr[head[c[a]]];
}
if(pos[a]>pos[b]) {
swap(a,b);
}
ans=max(ans,query(1,1,n,pos[a],pos[b]));
return ans;
}
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int main() {
int q;
fin>>n>>q;
for(int i=1; i<=n; i++) {
fin>>val[i];
}
for(int i=0; i<n-1; i++) {
int u,v;
fin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
dfs(1,0);
ind=1;
head[1]=1;
heavy_dfs(1,0,1);
for(int i=1; i<=n; i++) {
update(1,1,n,pos[i],val[i]);
}
while(q--) {
int type,u,v;
fin>>type>>u>>v;
if(type==0) {
update(1,1,n,pos[u],v);
} else {
fout<<solve(u,v)<<'\n';
}
}
return 0;
}