#include<cstdio>
#include<vector>
#include<cstring>
int max2(int a,int b){
if(a>b)
return a;
return b;
}
int min2(int a,int b){
if(a<b)
return a;
return b;
}
void change(int&x,int&y){
int aux=x;
x=y;
y=aux;
}
using namespace std;
const int N=100000;
class Lant{
public:
int start;
vector<int>v;
int l;
Lant(){
}
Lant(int s,int ll){
start=s;
l=ll;
}
};
vector<int>g[N+1];
Lant lant[N+1];
int niv[N+1];
int father[N+1];
int whose[N+1];
int imp[N+1];
int subtree[N+1];
bool vis[N+1];
int cost[N+1];
int grand[N+1];
int v[N+1];
int t[4*N+1];
int n,k,vv,pp;
int res;
int left,right;
/// ///////////////////////////////////////////////////////////
void build(int pos,int st,int dr){
if(st==dr){
t[pos]=cost[v[st]];
return;
}
int m=(st+dr)/2;
build(pos*2,st,m);
build(pos*2+1,m+1,dr);
t[pos]=max2(t[pos*2],t[pos*2+1]);
}
void update(int pos,int st,int dr){
if(st==dr){
t[pos]=vv;
return;
}
int m=(st+dr)/2;
if(pp<=m)
update(pos*2,st,m);
else
update(pos*2+1,m+1,dr);
t[pos]=max2(t[pos*2],t[pos*2+1]);
}
int query(int pos,int st,int dr){
if(dr<left||st>right)
return 0;
if(left<=st&&dr<=right)
return t[pos];
int m=(st+dr)/2;
return max2(query(pos*2,st,m),query(pos*2+1,m+1,dr));
}
/// ////////////////////////////////////////////////////////////////
void dfs1(int dad){
vis[dad]=true;
int maxx=0;
subtree[dad]=1;
for(unsigned int i=0;i<g[dad].size();i++){
int son=g[dad][i];
if(!vis[son]){
father[son]=dad;
niv[son]=niv[dad]+1;
dfs1(son);
subtree[dad]+=subtree[son];
if(subtree[son]>maxx){
maxx=subtree[son];
whose[dad]=whose[son];
}
}
}
if(g[dad].size()==1&&dad!=1)
whose[dad]=++k;
lant[whose[dad]].v.push_back(dad);
}
void dfs2(int dad){
if(!grand[dad]){
imp[dad]=1;
grand[dad]=dad;
}
vis[dad]=true;
for(unsigned int i=0;i<g[dad].size();i++){
int son=g[dad][i];
if(!vis[son]){
if(whose[dad]==whose[son]){
imp[son]=imp[dad]+1;
grand[son]=grand[dad];
}
dfs2(son);
}
}
}
void set_arbint(){
lant[0].start=1;
int x=0;
for(int i=1;i<=k;i++){
lant[i].start=lant[i-1].start+lant[i-1].l;
lant[i].l=lant[i].v.size();
for(unsigned int j=lant[i].v.size();j!=0;j--)
v[++x]=lant[i].v[j-1];
}
build(1,1,n);
}
int trans(int p){
int r=lant[whose[p]].start;
r+=imp[p]-1;
return r;
}
void heavy_update(int p,int vl){
cost[p]=vl;
pp=trans(p);
vv=vl;
update(1,1,n);
}
int heavy_query(int x,int y){
res=0;
if(niv[grand[x]]>niv[grand[y]])
change(x,y);
while(true){
if(grand[x]==grand[y]){
left=min2(trans(x),trans(y));
right=max2(trans(x),trans(y));
res=max2(res,query(1,1,n));
break;
}
left=trans(grand[y]);
right=trans(y);
res=max2(res,query(1,1,n));
y=father[grand[y]];
if(niv[grand[x]]>niv[grand[y]])
change(x,y);
}
return res;
}
int main(){
int q;
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&cost[i]);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
niv[1]=1;
dfs1(1);
memset(vis,0,sizeof(vis));
dfs2(1);
set_arbint();
while(q--){
int t,x,y;
scanf("%d%d%d",&t,&x,&y);
if(t==0)
heavy_update(x,y);
else
printf("%d\n",heavy_query(x,y));
}
return 0;
}