#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int DIM = 100005;
int n,m,val[DIM],t,x,y,Cnt[DIM],nrChains=0,WhatChain[DIM],PosInChain[DIM];
int D[DIM],MaxSum[DIM],Best[DIM],Parent[DIM],Tree[DIM*4+5],Prev[DIM],ans;
bool seen[DIM];
vector <int> G[DIM],Chains[DIM];
void Read()
{
fin>>n>>m;
for(int i=1;i<=n;i++)
fin>>val[i];
for(int i=1;i<n;i++)
{
fin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
}
void DFS(int node)
{
Cnt[node]=1;
vector <int> ::iterator it;
for(it=G[node].begin();it!=G[node].end();it++)
{
if(!Cnt[*it])
{
D[*it]=D[node]+1;
DFS(*it);
if(Cnt[*it]>MaxSum[node])
{
MaxSum[node]=Cnt[*it];
Best[node]=(*it);
}
Cnt[node]+=Cnt[*it];
}
}
}
void GetChains(int node)
{
seen[node]=1;
vector <int> ::iterator it;
for(it=G[node].begin();it!=G[node].end();it++)
{
if(!seen[*it])
GetChains(*it);
}
if(Cnt[node]==1)
{
nrChains++;
WhatChain[node]=nrChains;
PosInChain[node]=1;
}
else
{
WhatChain[node]=WhatChain[Best[node]];
PosInChain[node]=PosInChain[Best[node]]+1;
for(it=G[node].begin();it!=G[node].end();it++)
{
if((*it)!=Best[node])
Parent[WhatChain[*it]]=node;
}
}
Chains[WhatChain[node]].push_back(node);
}
void UpdateTree(int nod, int st, int dr, int pos, int value)
{
if(st==dr)
{
Tree[nod]=value;
return;
}
int mij=(st+dr)>>1;
if(pos<=mij)
UpdateTree(2*nod,st,mij,pos,value);
else
UpdateTree(2*nod+1,mij+1,dr,pos,value);
Tree[nod]=max(Tree[2*nod],Tree[2*nod+1]);
}
void QueryTree(int nod, int st, int dr, int a, int b)
{
if(st>=a && dr<=b)
{
ans=max(ans,Tree[nod]);
return;
}
int mij=(st+dr)>>1;
if(a<=mij)
QueryTree(2*nod,st,mij,a,b);
if(b>mij)
QueryTree(2*nod+1,mij+1,dr,a,b);
}
void Query()
{
while(m--)
{
fin>>t>>x>>y;
if(!t)
UpdateTree(1,1,n,Prev[WhatChain[x]-1]+PosInChain[x],y);
else
{
ans=0;
while(WhatChain[x]!=WhatChain[y])
{
int p1=Chains[WhatChain[x]][Chains[WhatChain[x]].size()-1];
int p2=Chains[WhatChain[y]][Chains[WhatChain[y]].size()-1];
if(D[p1]>D[p2])
{
QueryTree(1,1,n,Prev[WhatChain[x]-1]+PosInChain[x],Prev[WhatChain[x]]);
x=Parent[WhatChain[x]];
}
else if(D[p1]<=D[p2])
{
QueryTree(1,1,n,Prev[WhatChain[y]-1]+PosInChain[y],Prev[WhatChain[y]]);
y=Parent[WhatChain[y]];
}
}
if(PosInChain[x]>PosInChain[y])
swap(x,y);
QueryTree(1,1,n,Prev[WhatChain[x]-1]+PosInChain[x],Prev[WhatChain[x]-1]+PosInChain[y]);
fout<<ans<<'\n';
}
}
}
void UpdateChains()
{
int nr=0;
for(int i=1;i<=nrChains;i++)
{
Prev[i]=Prev[i-1]+Chains[i].size();
for(unsigned j=0;j<Chains[i].size();j++)
{
nr++;
UpdateTree(1,1,n,nr,val[Chains[i][j]]);
}
}
}
int main()
{
Read();
DFS(1);
GetChains(1);
UpdateChains();
Query();
}