#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
typedef vector<int>::iterator it;
#define MaxN 100100
#define mid ((li+ls)>>1)
#define fs (poz<<1)
#define fd ((poz<<1)+1)
#define tata (poz>>1)
int N,M,acc;
int D[MaxN];
vector<int> A[MaxN];
vector<int> Path[MaxN];
int H[MaxN], G[MaxN];
int whatPath[MaxN], whatPoz[MaxN];
vector<int> AINT[MaxN];
void citire(void)
{
int a,b;
f >> N >> M;
for(int i=1;i<=N;i++)
f >> D[i];
for(int i=1;i<N;i++)
{
f >> a >> b;
A[a].push_back(b);
A[b].push_back(a);
}
}
inline void HPD(int nod)
{
int maxG = 0, pozMaxG = -1;
G[nod] = 1;
for(it i=A[nod].begin();i<A[nod].end();i++)
if(!H[*i])
{
H[*i] = H[nod] + 1;
HPD(*i);
G[nod] += G[*i];
if(maxG < G[*i])
maxG = G[*i],
pozMaxG = *i;
}
if(pozMaxG == -1)
{
Path[++acc].push_back(0);
Path[acc].push_back(nod);
whatPath[nod] = acc;
whatPoz[nod] = 1;
}
else
{
Path[whatPath[pozMaxG]].push_back(nod);
whatPath[nod] = whatPath[pozMaxG];
whatPoz[nod] = whatPoz[pozMaxG]+1;
for(it i=A[nod].begin();i<A[nod].end();i++)
if(H[nod] < H[*i] && pozMaxG != *i)
Path[whatPath[*i]][0] = nod;
}
}
inline void make(int path, int poz, int li, int ls)
{
if(li == ls)
{
AINT[path][poz] = D[Path[path][li]];
return ;
}
make(path, fs, li, mid);
make(path, fd, mid+1, ls);
AINT[path][poz] = max(AINT[path][fs], AINT[path][fd]);
}
inline void update(int path, int poz, int li, int ls, int rPoz, int val)
{
if(li == ls)
{
AINT[path][poz] = val;
return ;
}
if(rPoz <= mid)
update(path, fs, li, mid, rPoz, val);
else
update(path, fd, mid+1, ls, rPoz, val);
AINT[path][poz] = max(AINT[path][fs], AINT[path][fd]);
}
inline int query(int path, int poz, int li, int ls, int a, int b)
{
int maxInt = 0;
if(a <= li && ls <= b)
return AINT[path][poz];
if(a <= mid)
maxInt = query(path, fs, li, mid, a, b);
if(mid < b)
maxInt = max(maxInt, query(path, fd, mid+1, ls, a, b));
return maxInt;
}
void makeAINT(void)
{
for(int i=1;i<=acc;i++)
{
AINT[i].reserve(5*Path[i].size());
make(i,1,1,Path[i].size()-1);
}
}
inline void swap(int &a, int &b)
{
int aux = a;
a = b;
b = aux;
}
inline int specified_query(int x, int y)
{
int maxSpec = 0;
if(Path[whatPath[x]][0] > Path[whatPath[y]][0])
swap(x,y);
if(whatPath[x] == whatPath[y])
return query(whatPath[x], 1, 1, Path[whatPath[x]].size()-1,
min(whatPoz[y], whatPoz[x]), max(whatPoz[x], whatPoz[y]));
maxSpec = query(whatPath[y], 1, 1, Path[whatPath[y]].size()-1, whatPoz[y], Path[whatPath[y]].size()-1);
y = Path[whatPath[y]][0];
return max(maxSpec, specified_query(x,y));
}
int main(void)
{
int op, x, y;
citire();
H[1] = 1;
HPD(1);
makeAINT();
for(int i=1;i<=M;i++)
{
f >> op >> x >> y;
if(!op)
update(whatPath[x], 1, 1, Path[whatPath[x]].size()-1, whatPoz[x], y);
else
g << specified_query(x,y) << "\n";
}
}