#include<fstream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m,nrlant;
vector <int> G[100100];
bool viz[100100];
int val[100100],weight[100100];
int lant[100100],dim[100100],lanttata[100100];
vector <int> L[100100];
int Aint[500000],start[100100],sol,poz[100100];
int niv[100100],nivlant[100100],poznod[100100];
inline void DFS(int x,int tata)
{
viz[x]=true;
weight[x]=1;
vector <int>::iterator it;
bool frunza=true;
int heavynod=0;
for(it=G[x].begin();it!=G[x].end();it++)
{
if(!viz[*it])
{
frunza=false;
niv[*it]=niv[x]+1;
DFS(*it,x);
weight[x]+=weight[*it];
if(!heavynod || weight[heavynod]<weight[*it])
heavynod=*it;
}
}
if(frunza)
{
lant[x]=++nrlant;
dim[nrlant]=1;
L[nrlant].push_back(x);
poz[x]=0;
}
else
{
lant[x]=lant[heavynod];
dim[lant[x]]++;
L[lant[x]].push_back(x);
poz[x]=L[lant[x]].size()-1;
for(it=G[x].begin();it!=G[x].end();it++)
{
if(*it==heavynod || *it==tata)
continue;
lanttata[lant[*it]]=x;
nivlant[lant[*it]]=niv[x];
}
}
}
inline void Build(int nod,int st,int dr,int delay,int lant)
{
if(st==dr)
{
Aint[nod+delay]=val[L[lant][st-1]];
return;
}
int mij=(st+dr)/2;
Build(2*nod,st,mij,delay,lant);
Build(2*nod+1,mij+1,dr,delay,lant);
Aint[nod+delay]=max(Aint[2*nod+delay],Aint[2*nod+1+delay]);
}
inline void Update(int nod,int st,int dr,int delay,int poz,int v)
{
if(st==dr)
{
Aint[nod+delay]=v;
return;
}
int mij=(st+dr)/2;
if(poz<=mij)
Update(2*nod,st,mij,delay,poz,v);
else
Update(2*nod+1,mij+1,dr,delay,poz,v);
Aint[nod+delay]=max(Aint[2*nod+delay],Aint[2*nod+1+delay]);
}
inline void Query(int nod,int st,int dr,int delay,int a,int b)
{
if(a<=st && dr<=b)
{
sol=max(sol,Aint[nod+delay]);
return;
}
int mij=(st+dr)/2;
if(a<=mij)
Query(2*nod,st,mij,delay,a,b);
if(mij+1<=b)
Query(2*nod+1,mij+1,dr,delay,a,b);
}
inline void DescompunereLanturi()
{
DFS(1,0);
int i,j;
vector <int>::iterator it;
for(i=1;i<=nrlant;i++)
{
reverse(L[i].begin(),L[i].end());
for(it=L[i].begin(),j=1;it!=L[i].end();it++,j++)
poznod[*it]=j;
if(i>1)
start[i]=start[i-1]+4*dim[i-1];
Build(1,1,dim[i],start[i],i);
}
}
int main()
{
int i,x,y,op;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
fin>>n>>m;
for(i=1;i<=n;i++)
fin>>val[i];
for(i=1;i<n;i++)
{
fin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
DescompunereLanturi();
for(i=1;i<=m;i++)
{
fin>>op>>x>>y;
if(op==0)
Update(1,1,dim[lant[x]],start[lant[x]],poznod[x],y);
else
{
sol=0;
while(1)
{
if(lant[x]==lant[y])
{
if(niv[x]>niv[y])
swap(x,y);
Query(1,1,dim[lant[x]],start[lant[x]],poznod[x],poznod[y]);
break;
}
if(nivlant[lant[x]]<nivlant[lant[y]])
swap(x,y);
Query(1,1,dim[lant[x]],start[lant[x]],1,poznod[x]);
x=lanttata[lant[x]];
}
fout<<sol<<"\n";
}
}
fin.close();
fout.close();
return 0;
}