#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n,m,val[100005],niv[100005],in[100005],out[100005],dp[18][100005];
vector<int> muchii[100005];
int where[100005],poz[100005];
int par[100005];
bool isheavy[100005];
int timp,nr[100005];
vector<vector<int>> arb;
vector<int> emp;
int path[100005],last[100005];
int lg[100005];
void dfs(int nod)
{
timp++;
in[nod]=timp;
nr[nod]=1;
dp[0][nod]=par[nod];
for(int i=1;i<=17;i++)
dp[i][nod]=dp[i-1][dp[i-1][nod]];
for(int i:muchii[nod])
if(i!=par[nod])
{
par[i]=nod;
niv[i]=niv[nod]+1;
dfs(i);
nr[nod]+=nr[i];
}
out[nod]=timp;
int who=0,maxim=0;
for(int i:muchii[nod])
if(i!=par[nod])
if(nr[i]>maxim)
{
maxim=nr[i];
who=i;
}
if(maxim>0)
isheavy[who]=1;
}
void arbupdate(int ind,int nod,int st,int dr,int p,int x)
{
if(st==dr)
{
arb[ind][nod]=x;
return;
}
int mij=(st+dr)/2;
if(p<=mij)
arbupdate(ind,nod*2,st,mij,p,x);
else
arbupdate(ind,nod*2+1,mij+1,dr,p,x);
arb[ind][nod]=max(arb[ind][nod*2],arb[ind][nod*2+1]);
}
int arbquery(int ind,int nod,int st,int dr,int a,int b)
{
if(st>=a&&dr<=b)
return arb[ind][nod];
int mij=(st+dr)/2;
int rez=0;
if(a<=mij)
rez=max(rez,arbquery(ind,nod*2,st,mij,a,b));
if(b>mij)
rez=max(rez,arbquery(ind,nod*2+1,mij+1,dr,a,b));
return rez;
}
bool isancestor(int a,int b)
{
return in[a]<=in[b]&&out[a]>=out[b];
}
int LCA(int a,int b)
{
if(niv[a]>niv[b])
swap(a,b);
if(isancestor(a,b))
return a;
for(int i=17;i>=0;i--)
if(dp[i][a]!=0&&!isancestor(dp[i][a],b))
a=dp[i][a];
return par[a];
}
void build()
{
arb.push_back(emp);
int cnt=0;
for(int start=1;start<=n;start++)
{
bool good=1;
for(int i:muchii[start])
if(i!=par[start])
if(isheavy[i])
good=0;
if(good)
{
vector<int> pp;
cnt++;
arb.push_back(emp);
int nod=start;
while(true)
{
pp.push_back(nod);
if(isheavy[nod])
nod=par[nod];
else
break;
}
for(int i=0;i<pp.size();i++)
{
where[pp[i]]=cnt;
poz[pp[i]]=i+1;
}
int lg=pp.size();
path[cnt]=pp.size();
last[cnt]=pp.back();
arb[cnt].resize(3*lg+5);
}
}
}
void update(int nod,int val)
{
int ind=where[nod];
int p=poz[nod];
arbupdate(ind,1,1,path[ind],p,val);
}
int query(int a,int lca)
{
int rez=0;
while(niv[a]>=niv[lca])
{
int ind=where[a];
int p=poz[a];
if(niv[last[ind]]>=niv[lca])
{
rez=max(rez,arbquery(ind,1,1,path[ind],p,path[ind]));
a=par[last[ind]];
continue;
}
else
{
int last=p+niv[a]-niv[lca];
rez=max(rez,arbquery(ind,1,1,path[ind],p,last));
break;
}
}
return rez;
}
int main()
{
ios_base::sync_with_stdio(false);
fin.tie(0);
fin>>n>>m;
for(int i=1;i<=n;i++)
fin>>val[i];
for(int i=1;i<n;i++)
{
int a,b;
fin>>a>>b;
muchii[a].push_back(b);
muchii[b].push_back(a);
}
niv[1]=1;
dfs(1);
build();
for(int i=1;i<=n;i++)
update(i,val[i]);
while(m--)
{
int tip;
fin>>tip;
if(tip==0)
{
int nod,x;
fin>>nod>>x;
val[nod]=x;
update(nod,x);
}
else
{
int a,b;
fin>>a>>b;
int lca=LCA(a,b);
fout<<max(query(a,lca),query(b,lca))<<'\n';
}
}
return 0;
}