/*
Descompunerea in lanturi
Complexitate:O(M*log2(N))
*/
#include <iostream>
#include <stdio.h>
#include <vector>
#define NMax 100005
#define ArbMax 400005
using namespace std;
vector<int> Graf[NMax],Chain[NMax];
int N,M,value[NMax],lant[NMax],level[NMax],weight[NMax];
int tata[NMax],position[NMax],aibase[NMax];
int Arb[ArbMax],vpos;
bool mark[NMax];
int n1;
void DFS(int nod)
{
int MaxW=0;
mark[nod]=true,weight[nod]=1;
for(vector<int>::iterator it=Graf[nod].begin();it!=Graf[nod].end();it++)
{
if(mark[*it]==true)
continue;
tata[*it]=nod;
level[*it]=level[nod]+1;
DFS(*it);
if(weight[*it]>weight[MaxW])
MaxW=*it;
weight[nod]=weight[nod]+weight[*it];
}
if(MaxW)
lant[nod]=lant[MaxW];
else
lant[nod]=++n1;
Chain[lant[nod]].push_back(nod);
}
void BuildArbore(int nod,int s,int d)
{
if(s==d)
{
Arb[nod]=value[aibase[s]];
return;
}
int mij=(s+d)/2;
BuildArbore(nod*2,s,mij);
BuildArbore(nod*2+1,mij+1,d);
Arb[nod]=max(Arb[nod*2],Arb[2*nod+1]);
}
void UpdateArbore(int x,int val,int nod,int s,int d)
{
if(s==d)
{
Arb[nod]=val;
return;
}
int mij=(s+d)/2;
if(x>mij)
UpdateArbore(x,val,nod*2+1,mij+1,d);
else
UpdateArbore(x,val,nod*2,s,mij);
Arb[nod]=max(Arb[2*nod],Arb[2*nod+1]);
}
inline int AflaTata(int x)
{
return tata[Chain[x].back()];
}
int AflaRang(int x,int y,int nod,int s,int d)
{
if(d<x || s>y)
return 0;
if(s>=x && d<=y)
return Arb[nod];
return max(AflaRang(x,y,nod*2,s,(s+d)/2),AflaRang(x,y,nod*2+1,(s+d)/2+1,d));
}
int Query(int x,int y)
{
int vmx=0;
while(lant[x]!=lant[y])
{
int ttx=AflaTata(lant[x]),tty=AflaTata(lant[y]);
if(level[ttx]>level[tty])
{
vmx=max(vmx,AflaRang(position[x],position[Chain[lant[x]].back()],1,1,N));
x=ttx;
}
else
{
vmx=max(vmx,AflaRang(position[y],position[Chain[lant[y]].back()],1,1,N));
y=tty;
}
}
if(position[x]>position[y])
swap(x,y);
return max(vmx,AflaRang(position[x],position[y],1,1,N));
}
int main()
{
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
int i,x,y;
scanf("%d%d",&N,&M);
for(i=1;i<=N;++i)
scanf("%d",&value[i]);
for(i=1;i<=N-1;++i)
{
scanf("%d%d",&x,&y);
Graf[x].push_back(y);
Graf[y].push_back(x);
}
level[1]=1;
DFS(1);
for(i=1;i<=n1;++i)
for(size_t j=0;j<Chain[i].size();++j)
aibase[position[Chain[i][j]]=++vpos]=Chain[i][j];
BuildArbore(1,1,N);
while(M--)
{
scanf("%d%d%d",&i,&x,&y);
if(i)
printf("%d\n",Query(x,y));
else
UpdateArbore(position[x],y,1,1,N);
}
}