#include<bits/stdc++.h>
#define dim_max 1800001
#define nmax 100001
using namespace std;
//matricea arborelui
int n,v[nmax],m;
vector<int> G[nmax],T[nmax];
struct Nod
{
int tata;
int nivel;
int subarb;
int poz;
int chain;
int weight;
};
Nod nodes[nmax];
struct muchie
{ int weight;
int nod_deep;
};
int Arb[4*nmax];
void dfs(int curr,int prev,int lev)
{
int i;
nodes[curr].tata=prev;
nodes[curr].nivel=lev;
nodes[curr].subarb=1;
//pentru toti fiii lui nodului curent
vector<int>::iterator it;
for(it=G[curr].begin();it!=G[curr].end();it++)
//for(i=1;i<=n;i++)
if((*it)!=nodes[curr].tata)
{
dfs((*it),curr,lev+1);
nodes[curr].subarb+=nodes[*it].subarb;
}
}
void hld(int curr_node,int *pos,int *curr_chain,int chain_heads[])
{
if(chain_heads[*curr_chain]==-1)
chain_heads[*curr_chain]=curr_node;
nodes[curr_node].chain=*curr_chain;
nodes[curr_node].poz=++(*pos);
Arb[*pos]=v[curr_node];
//cout<<curr_node<<' '<<(*pos)<<endl;
int special=-1,j;
vector<int>::iterator it;
for(it=G[curr_node].begin();it!=G[curr_node].end();it++)
if((*it)!=nodes[curr_node].tata )
if(special==-1 || nodes[special].subarb<nodes[*it].subarb)
special=(*it);
//cout<<special<<' ';
if(special!=-1)
hld(special,pos,curr_chain,chain_heads);
//pentru fiii normali
for(it=G[curr_node].begin();it!=G[curr_node].end();it++)
if((*it)!=nodes[curr_node].tata && (*it)!=special)
{
//cout<<curr_node<<' '<<*curr_chain<<endl;
++(*curr_chain);
hld((*it),pos,curr_chain,chain_heads);
}
}
//construiesc arborele de intervale pentru Arb
int SegTree[4*nmax];
int ConstrArb(int nod,int st,int dr)
{
int mij=(st+dr)/2;
if(st==dr)
{SegTree[nod]=Arb[st];
return SegTree[nod];
}
// else //[st,dr] e inclus in a[b]
// SegTree[nod]=max(SegTree[2*nod],SegTree[2*nod+1]);
else
{
SegTree[nod]=max(ConstrArb(nod*2,st,mij),ConstrArb(nod*2+1,mij+1,dr));
return SegTree[nod];
}
}
//operatia de tip 0
void update(int nod,int st,int dr,int x,int val)
{
//tot pe interval deschis
if(x<st || x>dr);
int mij=(st+dr)/2;
if(st==x && dr==x)
{
SegTree[nod]=val;
return;
}
else
{
if(x<=mij)
update(nod*2,st,mij,x,val);
if(x>mij)
update(nod*2+1,mij+1,dr,x,val);
SegTree[nod]=max(SegTree[2*nod],SegTree[2*nod+1]);
}
}
int size,euler[dim_max],lev[dim_max],Pos[nmax];
int lookup[dim_max][18];
void Euler_tour(int nod,int level)
{
euler[size]=nod;
lev[size]=level;
Pos[nod]=size;
++size;
vector<int>::iterator it;
for(it=T[nod].begin();it!=T[nod].end();it++)
{
Euler_tour(*it,level+1);
euler[size]=nod;
lev[size]=level;
++size;
}
}
void preprocess(int arr[],int k)
{
int i,j;
//initializare
for(i=0;i<k;i++)
lookup[i][0]=i;
for(j=1;(1<<j)<k;j++)
for(i=0;i+(1<<j)-1<k;i++)
if(arr[lookup[i][j-1]]<=arr[lookup[i+(1<<(j-1))][j-1]])
lookup[i][j]=lookup[i][j-1];
else
lookup[i][j]=lookup[i+(1<<(j-1))][j-1];
}
int lca(int nod1,int nod2)
{
int l,r,dim;
l=Pos[nod1];
r=Pos[nod2];
if(l>r) swap(l,r);
dim=(int)log2(r-l+1);
if(lev[lookup[l][dim]]<=lev[lookup[r-(1<<dim)+1][dim]])
return euler[lookup[l][dim]];
else
return euler[lookup[r-(1<<dim)+1][dim]];
}
//intoarce maximul din [a...b]
int query_1(int nod,int st,int dr,int a,int b)
{
int mij=(st+dr)/2,c,d;
if(a<=st && b>=dr)
return SegTree[nod];
if(dr<a || st>b)
return -1;
return max(query_1(2*nod,st,mij,a,b),query_1(2*nod+1,mij+1,dr,a,b));
}
//functia query la t=1
int crawling_2(int u,int z,int chain_heads[])
{
int chain_u,chain_z,ans=0,ok=0;
while(!ok )
{
chain_u=nodes[u].chain;
chain_z=nodes[z].chain;
if(chain_u==chain_z)
{ans=max(ans,query_1(1,1,n,min(nodes[u].poz,nodes[z].poz),max(nodes[u].poz,nodes[z].poz)));
ok=1;
}
else
{
if(nodes[nodes[chain_heads[chain_z]].tata].nivel>nodes[nodes[chain_heads[chain_u]].tata].nivel)
swap(u,z);
ans=max(ans,query_1(1,1,n,nodes[chain_heads[chain_u]].poz,nodes[u].poz));
u=nodes[chain_heads[chain_u]].tata;
//z=nodes[chain_heads[chain_z]].tata;
if(u==-1) u=1;
//if(z==-1) z=1;
}
}
return ans;
}
int max_node(int u,int v,int chain_heads[])
{
int Lca=lca(u,v),ans=0;
ans=max(crawling_2(u,Lca,chain_heads),crawling_2(v,Lca,chain_heads));
return ans;
}
int main()
{
int i,a,b,chain_heads[nmax],t;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
fin>>n>>m;
//memset(tree,-1,sizeof(tree));
for(i=1;i<=n;i++)
fin>>v[i];
memset(chain_heads,-1,sizeof(chain_heads));
for(i=1;i<n;i++)
{
fin>>a>>b;
G[a].push_back(b);
G[b].push_back(a);
T[a].push_back(b);
}
int edge_counted=0,curr_chain=1;
dfs(1,-1,0);
//for(i=1;i<=n;i++)
// cout<<nodes[i].subarb<<' ';
hld(1,&edge_counted,&curr_chain,chain_heads);
//cout<<endl;
//for(i=1;i<=pos;i++)
// cout<<Arb[i]<<' ';
int root=1;
ConstrArb(root,1,n);
root=1;
Euler_tour(root,0);
preprocess(lev,size);
//cout<<SegTree[5];
//cout<<nodes[9].poz;
//cout<<update(root,1,n+1,nodes[3].poz,1);
//for(i=1;i<=curr_chain;i++)
//cout<<chain_heads[i]<<' ';
for(i=1;i<=m;i++)
{
fin>>t>>a>>b;
if(!t)
update(1,1,n,nodes[a].poz,b);
if(t==1)
fout<<max_node(a,b,chain_heads)<<'\n';
}
fin.close();
fout.close();
//cout<<LCA(4,5);
//cout<<query_1(1,1,n+1,3,3);
}