#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define pb push_back
#define MAX 100001
#define INF 2000000001
int N , M , v[MAX] , d[MAX] , t[MAX] , dim , lev[MAX] , w_path[MAX] , niv[MAX] , tp[MAX] ;
int poz[MAX];
vector<int> G[MAX] , path[MAX] , AI[MAX];
void read();
void DFS(int nod , int l);
void DFS1(int nod);
bool comp(int x , int y)
{
return lev[x] < lev[y];
}
void update(vector<int> &A,int n , int l , int r , int poz , int val);
int query(vector<int> A,int n , int l , int r , int a , int b);
int query1(int x , int y);
int main()
{
int x , y, z;
read();
DFS(1,0);
DFS1(1);
for(int i = 1 ; i<= dim ; ++i )
sort(path[i].begin(),path[i].end(),comp);
for(int i = 1 ; i<= dim ; ++i )
AI[i].resize(path[i].size()*5);
for(int i = 1 ; i<= dim ; ++i )
for(int j = 0 ; j <(int)path[i].size() ; ++j )
poz[path[i][j]] = j;
for(int i = 1 ; i<= N ; ++i )
update(AI[w_path[i]],1,0,path[w_path[i]].size()-1,poz[i],v[i]);
for(int i = 2 ; i<= N ; ++i )
if(w_path[i] != w_path[t[i]])
tp[w_path[i]] = t[i];
int p = 0;
for(; M-- && p <= 920 ; )
{
scanf("%d%d%d" , &z , &x , &y );
if(z == 0)
{
update(AI[w_path[x]],1,0,path[w_path[x]].size()-1,poz[x],y);
v[x] = y;
}
else
printf("%d\n" , query1(x,y)),p++;;
}
for(; M--; )
{
scanf("%d%d%d" , &z , &x , &y );
if(z == 0)
{
update(AI[w_path[x]],1,0,path[w_path[x]].size()-1,poz[x],y);
v[x] = y;
}
else
printf("%d\n" , query1(x,y)),p++;;
}
return 0;
}
void read()
{
int x , y;
freopen("heavypath.in" , "r" , stdin );
freopen("heavypath.out" , "w" , stdout );
scanf("%d%d" , &N , &M );
for(int i = 1 ; i<= N ; ++i )
scanf("%d" , &v[i] );
for(int i = 1 ; i< N ; ++i )
{
scanf("%d%d" , &x , &y );
G[x].pb(y);
G[y].pb(x);
}
}
void DFS(int nod , int l)
{
int maxx = 0 , fiu;
lev[nod] = l;
if(G[nod].size() == 1 && G[nod][0] == t[nod])
{
path[++dim].pb(nod);
w_path[nod] = dim;
d[nod] = 1;
}
else
{
for(int i = 0 ; i <(int)G[nod].size() ; ++i )
if(G[nod][i] != t[nod])
{
t[G[nod][i]] = nod;
DFS(G[nod][i],l+1);
if(d[G[nod][i]] > maxx)
{
maxx = d[G[nod][i]];
fiu = G[nod][i];
}
d[nod]+=d[G[nod][i]];
}
d[nod]++;
path[w_path[fiu]].pb(nod);
w_path[nod] = w_path[fiu];
}
}
void DFS1(int nod)
{
for(int i = 0 ; i<(int)G[nod].size() ; ++i )
if(G[nod][i] != t[nod])
{
if(w_path[nod] != w_path[G[nod][i]])
niv[w_path[G[nod][i]]] = niv[nod] + 1;
DFS1(G[nod][i]);
}
}
void update(vector<int> &A,int n , int l , int r , int poz , int val)
{
if(l == r)A[n] = val;
else
{
int m = (l+r)/2;
if(poz <= m)
update(A,2*n,l,m,poz,val);
if(poz > m)
update(A,2*n+1,m+1,r,poz,val);
A[n] = max(A[2*n],A[2*n+1]);
}
}
int query1(int x , int y)
{
int rez = max(v[x],v[y]) , aux;
while(w_path[x] != w_path[y])
{
if(niv[w_path[x]] < niv[w_path[y]])
{
rez = max(rez,query(AI[w_path[y]],1,0,path[w_path[y]].size()-1,0,poz[y]));
y = tp[w_path[y]];
}
else
{
rez = max(rez,query(AI[w_path[x]],1,0,path[w_path[x]].size()-1,0,poz[x]));
x = tp[w_path[x]];
}
}
if(lev[x] > lev[y]){aux = x;x=y;y=aux;}
rez = max(rez,query(AI[w_path[x]],1,0,path[w_path[x]].size()-1,poz[x],poz[y]));
return rez;
}
int query(vector<int> A , int n , int l , int r , int a , int b)
{
if(a <= l && b >= r )return A[n];
else
{
int m = (l+r)/2;
int maxx = -INF;
if(a <= m)
maxx = query(A,2*n,l,m,a,b);
if(b > m)
maxx = max(maxx,query(A,2*n+1,m+1,r,a,b));
return maxx;
}
}