#include <algorithm>
#include <cstdio>
#include <vector>
#include <bitset>
using namespace std;
const int N=100005;
class SegmentTree{
public:
SegmentTree(const int _n=0, vector<int> _vals=vector<int>()):
n(_n),
aint(vector<int>(5*_n+2)),
vals(_vals)
{
if(_n) Build(1, 1, n);
}
void update(const int poz, const int val)
{
X=poz;
Y=val;
Update(1, 1, n);
}
int query(const int st, const int dr)
{
ret=0;
X=st;
Y=dr;
Query(1, 1, n);
return ret;
}
private:
int n, X, Y, ret;
vector<int> aint, vals;
void Build(int nod, int l, int r)
{
if(l==r)
{
aint[nod]=vals[l];
return;
}
int mid=(l+r)/2;
Build(2*nod, l, mid);
Build(2*nod+1, mid+1, r);
aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}
void Update(int nod, int l, int r)
{
if(l==r)
{
aint[nod]=Y;
return;
}
int mid=(l+r)/2;
if(X<=mid) Update(2*nod, l, mid);
else Update(2*nod+1, mid+1, r);
aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}
void Query(int nod, int l, int r)
{
if(X<=l&&r<=Y)
{
if(aint[nod]>ret) ret=aint[nod];
return;
}
int mid=(l+r)/2;
if(X<=mid) Query(2*nod, l, mid);
if(Y>mid) Query(2*nod+1, mid+1, r);
}
};
int a[N], Lvl[N], f[N], nr[N], Path[N], Poz[N], Pathf[N];
int nrpaths;
vector<int> G[N], paths[N], values;
vector<SegmentTree> A;
void dfs1(const int n, const int fa)
{
f[n]=fa;
if(fa) G[n].erase(find(G[n].begin(), G[n].end(), fa));
nr[n]=1;
int nod=0;
for(auto p: G[n])
{
dfs1(p, n);
nr[n]+=nr[p];
if(nr[p]>nr[nod]) nod=p;
}
if(!nod) Path[n]=++nrpaths;
else Path[n]=Path[nod];
paths[Path[n]].push_back(n);
}
void dfs2(const int n)
{
for(auto p: G[n])
{
if(Path[p]!=Path[n])
{
Lvl[Path[p]]=Lvl[Path[n]]+1;
Pathf[Path[p]]=n;
}
dfs2(p);
}
}
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int n, q, i, j, x, y, sol=0, p;
scanf("%d%d", &n, &q);
for(i=1;i<=n;i++) scanf("%d", &a[i]);
for(i=1;i<n;i++)
{
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs1(1, 0);
A=vector<SegmentTree>(nrpaths+1);
for(i=1;i<=nrpaths;i++)
{
paths[i].push_back(0);
reverse(paths[i].begin(), paths[i].end());
for(vector<int>::iterator it=paths[i].begin();it!=paths[i].end();it++)
{
Poz[*it]=it-paths[i].begin();
values.push_back(a[*it]);
}
paths[i].clear();
A[i]=SegmentTree(values.size()-1, values);
values.clear();
}
dfs2(1);
while(q--)
{
scanf("%d%d%d", &i, &x, &y);
if(!i)
{
A[Path[x]].update(Poz[x], y);
}
else
{
i=Path[x];
j=Path[y];
sol=0;
while(i!=j)
{
if(Lvl[i]>Lvl[j])
{
p=A[i].query(1, Poz[x]);
if(sol<p) sol=p;
x=Pathf[i];
i=Path[x];
}
else
{
p=A[j].query(1, Poz[y]);
if(sol<p) sol=p;
y=Pathf[j];
j=Path[y];
}
}
p=A[i].query(min(Poz[x], Poz[y]), max(Poz[x], Poz[y]));
if(sol<p) sol=p;
printf("%d\n", sol);
}
}
}