#include <fstream>
#include <vector>
#include <cmath>
#define Nmax 100001
#define pb push_back
using namespace std;
ofstream g("heavypath.out");
struct nod{
nod *st,*dr;
int val;
nod (nod *_st,nod *_dr,int _val) : st(_st), dr(_dr), val(_val) {};
}*AINT[Nmax];
bool uz[Nmax];
vector<int> V[Nmax],L[Nmax];
int val[Nmax],x,y,Lid[Nmax],poz[Nmax],nrL,n,m,niv[Nmax],T[Nmax],t;
int lg(int x)
{
int rez = 1<<((int)log2(L[x].size()));
if (rez<L[x].size())
rez*=2;
return rez;
}
void update(nod *N,int st,int dr,int poz,int val)
{
if (st==dr)
{
N->val = val;
return;
}
int mid = (st+dr)/2;
if (poz>mid)
{
if (N->dr == NULL)
N->dr = new nod(NULL,NULL,0);
update(N->dr,mid+1,dr,poz,val);
}
else
{
if (N->st == NULL)
N->st = new nod(NULL,NULL,0);
update(N->st,st,mid,poz,val);
}
int a = 0,b = 0;
if (N->st!=NULL)
a = N->st->val;
if (N->dr!=NULL)
b = N->dr->val;
N->val = max(a,b);
}
void make_aint(vector<int> &L,int x)
{
AINT[x] = new nod(NULL,NULL,0);
for (int i=0;i<L.size();i++)
update(AINT[x],0,lg(x),i+1,val[L[i]]);
}
int dfs(int nod,int p,int nv)
{
int nr = 0,x,mx = -1,sav = -1;
niv[nod] = nv;
uz[nod] = 1;
for (int i=0;i<V[nod].size();i++)
{
if (!uz[V[nod][i]])
{
x = dfs(V[nod][i],nod,nv+1);
if (x>mx)
{
mx = x;
sav = V[nod][i];
}
nr+=x;
}
}
if (sav==-1)
{
Lid[nod] = ++nrL;
poz[nod] = L[Lid[nod]].size()+1;
L[Lid[nod]].pb(nod);
}
else
{
Lid[nod] = Lid[sav];
poz[nod] = L[Lid[nod]].size()+1;
L[Lid[nod]].pb(nod);
}
for (int i=0;i<V[nod].size();i++)
if (V[nod][i]!=p)
T[Lid[V[nod][i]]] = nod;
return nr+1;
}
int query(nod *N,int st,int dr,int L,int R)
{
if (L<=st && dr<=R)
return N->val;
int mid = (st+dr)/2,a=0,b=0;
if (L<=mid)
{
if (N->st == NULL)
N->st = new nod(NULL,NULL,0);
a = query(N->st,st,mid,L,R);
}
if (R>mid)
{
if (N->dr == NULL)
N->dr = new nod(NULL,NULL,0);
b = query(N->dr,mid+1,dr,L,R);
}
return max(a,b);
}
int path(int x,int y)
{
if (poz[x]>poz[y])
swap(x,y);
if (Lid[x]==Lid[y])
return query(AINT[Lid[x]],0,lg(Lid[x]),poz[x],poz[y]);
else if (T[Lid[x]] == T[Lid[y]])
return max(query(AINT[Lid[x]],0,lg(Lid[x]),poz[x],lg(Lid[x])),query(AINT[Lid[y]],0,lg(Lid[y]),poz[y],lg(Lid[y])));
if (niv[T[Lid[x]]]<niv[T[Lid[y]]])
swap(x,y);
return max(query(AINT[Lid[x]],0,lg(Lid[x]),poz[x],lg(Lid[x])),path(T[Lid[x]],y));
}
int main()
{
freopen("heavypath.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&val[i]);
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
V[x].pb(y);
V[y].pb(x);
}
dfs(1,-1,1);
for (int i=1;i<=nrL;i++)
make_aint(L[i],i);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&t,&x,&y);
if (t==0)
update(AINT[Lid[x]],0,lg(Lid[x]),poz[x],y);
if (t==1)
{
g<<path(x,y)<<'\n';
}
}
return 0;
}