#include <bits/stdc++.h>
#define eb emplace_back
#define ll long long
#define cin in
#define cout out
#define pii pair<int,int>
#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,k,a[MAX+5],first[MAX+5],niv[MAX+5],L[MAX+5],Lfather[MAX+5],len,Lniv[MAX+5];
int w[MAX+5],nrL,Tree[4*MAX+5],Ldecal[MAX+5];
vector<int> G[MAX+5];
bitset<MAX+5> p;
vector<int> Lant[2*MAX+5];
void read()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1,x,y;i<n;i++)
{
cin>>x>>y;
G[x].eb(y);
G[y].eb(x);
}
}
void dfs(int node)
{
p[node]=1;
w[node]=1;
int maxl=-1,leaf=1;
for(auto x: G[node])
{
if(p[x]) continue;
niv[x]=niv[node]+1;
leaf=0;
dfs(x);
w[node]+=w[x];
if(maxl==-1) maxl=x;
else if(w[maxl]<w[x]) maxl=x;
}
if(leaf)
{
nrL++;
L[node]=nrL;
Lant[L[node]].eb(node);
return;
}
L[node]=L[maxl];
Lant[L[node]].eb(node);
for(auto x: G[node])
{
if(x==maxl or niv[x]<niv[node]) continue;
Lfather[L[x]]=node;
Lniv[L[x]]=niv[node];
}
}
void build(int node,int l,int r,int decal,int pozl)
{
if(l==r)
{
Tree[node+decal]=a[Lant[pozl][l-1]];
}
else
{
int m=(l+r)/2;
build(2*node,l,m,decal,pozl);
build(2*node+1,m+1,r,decal,pozl);
Tree[node+decal]=max(Tree[2*node+decal],Tree[2*node+1+decal]);
}
}
void make_paths()
{
niv[1]=1;
dfs(1);
for(int i=1;i<=nrL;i++)
{
reverse(Lant[i].begin(),Lant[i].end());
if(i!=1)
Ldecal[i]=Ldecal[i-1]+Lant[i-1].size()*4;
build(1,1,Lant[i].size(),Ldecal[i],i);
}
}
void update(int node,int l,int r,int poz,int val,int decal)
{
if(l==r)
Tree[node+decal]=val;
else
{
int m=(l+r)/2;
if(poz<=m)
update(2*node,l,m,poz,val,decal);
else update(2*node+1,m+1,r,poz,val,decal);
Tree[node+decal]=max(Tree[2*node+decal],Tree[2*node+1+decal]);
}
}
int query(int node,int l,int r,int a,int b,int decal)
{
if(a<=l and r<=b)
return Tree[node+decal];
else
{
int m=(l+r)/2;
int left=INT_MIN,right=INT_MIN;
if(a<=m) left=query(2*node,l,m,a,b,decal);
if(b>m) right=query(2*node+1,m+1,r,a,b,decal);
return max(left,right);
}
}
void solve()
{
int t,x,y;
cin>>t>>x>>y;
if(t==0)
{
update(1,1,Lant[L[x]].size(),niv[x]-Lniv[L[x]],y,Ldecal[L[x]]);
}
else
{
int ans=INT_MIN;
while(1)
{
if(L[x]==L[y])
{
if(niv[x]>niv[y]) swap(x,y);
ans=max(ans,query(1,1,Lant[L[x]].size(),niv[x]-Lniv[L[x]],niv[y]-Lniv[L[x]],Ldecal[L[x]]));
break;
}
if(Lniv[L[x]]<Lniv[L[y]]) swap(x,y);
ans=max(ans,query(1,1,Lant[L[x]].size(),1,niv[x]-Lniv[L[x]],Ldecal[L[x]]));
x=Lfather[L[x]];
}
cout<<ans<<'\n';
}
}
int main()
{
read();
make_paths();
while(k--) solve();
return 0;
}