#include <bits/stdc++.h>
#define cin in
#define cout out
#define eb emplace_back
using namespace std;
const string file_name("heavypath");
ifstream in(file_name + ".in");
ofstream out(file_name + ".out");
const int MAX=1e5;
int n,m,t,x,y,nrL;
int val[MAX+5],w[MAX+5],niv[MAX+5],l[MAX+5],lFather[MAX+5],lNiv[MAX+5],lPozTree[MAX+5],Tree[4*MAX+5];
vector<int> G[MAX+5],L[MAX+5];
bitset<MAX+5> v;
void read()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>val[i];
for(int i=1;i<=n-1;i++)
{
cin>>x>>y;
G[x].eb(y);
G[y].eb(x);
}
}
void dfs(int nod)
{
v[nod]=1;
w[nod]=1;
int maxl=-1,frunza=-1;
for(auto x: G[nod])
{
if(v[x]) continue;
frunza=0;
niv[x]=niv[nod]+1;
dfs(x);
w[nod]+=w[x];
if(maxl==-1) maxl=x;
else if(w[maxl]<w[x]) maxl=x;
}
if(frunza)
{
l[nod]=++nrL;
L[l[nod]].eb(nod);
return;
}
l[nod]=l[maxl];
L[l[nod]].eb(nod);
for(auto x: G[nod])
{
if(x==maxl or niv[x]<niv[nod]) continue;
lFather[l[x]]=nod;
lNiv[l[x]]=niv[nod];
}
}
void build(int nod,int l,int r,int decal,int lant)
{
if(l==r)
Tree[nod+decal]=val[L[lant][l-1]];
else
{
int m=(l+r)/2;
build(2*nod,l,m,decal,lant);
build(2*nod+1,m+1,r,decal,lant);
Tree[nod+decal]=max(Tree[2*nod+decal],Tree[2*nod+1+decal]);
}
}
void make_paths()
{
niv[1]=1;
dfs(1);
for(int i=1;i<=nrL;i++)
{
reverse(L[i].begin(),L[i].end());
if(i>1) lPozTree[i]=lPozTree[i-1]+L[i-1].size()*4;/// marchez zona din Tree specifica lantului i
build(1,1,L[i].size(),lPozTree[i],i);
}
}
void update(int nod,int l,int r,int poz,int val,int decal)
{
if(l==r)
Tree[nod+decal]=val;
else
{
int m=(l+r)/2;
if(poz<=m) update(2*nod,l,m,poz,val,decal);
else update(2*nod+1,m+1,r,poz,val,decal);
Tree[nod+decal]=max(Tree[2*nod+decal],Tree[2*nod+1+decal]);
}
}
int query(int nod,int l,int r,int a,int b,int decal)
{
if(a<=l and r<=b)
return Tree[nod+decal];
int m=(l+r)/2,ans=INT_MIN;
if(a<=m) ans=max(ans,query(2*nod,l,m,a,b,decal));
if(b>m) ans=max(ans,query(2*nod+1,m+1,r,a,b,decal));
return ans;
}
void solve()
{
for(int i=1;i<=m;i++)
{
cin>>t>>x>>y;
if(t==0) update(1,1,L[l[x]].size(),niv[x]-lNiv[l[x]],y,lPozTree[l[x]]);
else
{
int ans=INT_MIN;
while(true)
{
if(l[x]==l[y])
{
if(niv[x]>niv[y]) swap(x,y);
ans=max(ans,query(1,1,L[l[x]].size(),niv[x]-lNiv[l[x]],niv[y]-lNiv[l[x]],lPozTree[l[x]]));
break;
}
if(lNiv[l[x]]<lNiv[l[y]])
swap(x,y);
ans=max(ans,query(1,1,L[l[x]].size(),1,niv[x]-lNiv[l[x]],lPozTree[l[x]]));
x=lFather[l[x]];
}
cout<<ans<<'\n';
}
}
}
int main()
{
read();
make_paths();
solve();
return 0;
}