#include <fstream>
#include <vector>
#include <bitset>
#include <queue>
#include <algorithm>
#include <utility>
#include <string.h>
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
const int MAXN = 100005;
const int oo = (1<<31)-1;
typedef vector<int> Graph[MAXN];
typedef vector<int> :: iterator It;
Graph G, P;
int N, M; /// Vertices and Queries
int V[MAXN], SubArb[MAXN], Paths = 1, Pos[MAXN], Where[MAXN], Parent[MAXN], Level[MAXN], Arb[MAXN*4];
bitset<MAXN> isFree;
struct ClassComp{
inline bool operator () (const int &a, const int &b) const{
return SubArb[a] > SubArb[b];
}
};
inline void DFs(int Node, int Father){
SubArb[Node] = 1;
Level[Node] = Level[Father] + 1;
for(It it = G[Node].begin() , fin = G[Node].end() ; it != fin ; ++ it){
if(*it == Father)
continue;
DFs(*it, Node);
SubArb[Node] += SubArb[*it];
}
}
inline void HeavyPath(int Node, int Father, int Path){
Where[Node] = Path;
for(It it = G[Node].begin(), fin = G[Node].end(); it != fin ; ++ it){
if(*it == Father)
continue;
if(!isFree[*it]){
isFree[*it] = true;
HeavyPath(*it, Node, Path);
}
else {
++Paths;
Parent[Paths] = Node;
HeavyPath(*it, Node, Paths);
}
}
}
inline void Update(int Node, int Left, int Right, int Pos, int Val, int Delta){
if(Left == Right){
Arb[Node + Delta] = Val;
return;
}
int mid = (Left + Right) >> 1;
if(Pos <= mid)
Update(2*Node, Left, mid, Pos, Val, Delta);
else Update(2*Node + 1, Left, mid+1, Pos, Val, Delta);
Arb[Node + Delta] = max(Arb[2*Node+Delta] , Arb[2*Node+1+Delta]);
}
inline void MakePath(){
DFs(1, 0);
for(int i = 1 ; i <= N ; ++ i)
sort(G[i].begin(), G[i].end() , ClassComp());
HeavyPath(1, 0, 1);
for(int i = 1 ; i <= Paths ; ++ i){
if(i > 1)
Pos[i] = Pos[i-1] + P[i-1].size() * 4;
for(It it = G[i].begin(), fin = G[i].end() ; it != fin ; ++ it)
Update(1, 1, (int)P[i].size() , Level[*it] - Level[Parent[Where[*it]]], V[*it], Pos[i]);
}
}
int query(int nod, int left, int right, int qleft, int qright, int decalaj)
{
if(qleft <= left && right <= qright)
return Arb[nod + decalaj];
int mid = (left+right)/2, rez = 0;
if(qleft <= mid)
rez = max(rez, query(nod * 2, left, mid, qleft, qright, decalaj));
if(mid < qright)
rez = max(rez, query(nod * 2 + 1, mid + 1, right, qleft, qright, decalaj));
return rez;
}
int main() {
cin >> N >> M;
for(int i = 1 ; i <= N ; ++ i)
cin >> V[i];
for(int i = 1 ; i != N ; ++ i) {
int X, Y;
cin >> X >> Y;
G[X].push_back(Y);
G[Y].push_back(X);
}
MakePath();
for(int i = 1 ; i <= M ; ++ i){
int t, x, y;
cin >> t >> x >> y; /// those
if(!t){
Update(1,1,(int)P[Where[x]].size(),Level[x]-Level[Parent[Where[x]]],y,Pos[Where[x]]);
}
else{
int sol=0;
// while(Where[x] != Where[y])
// {
// if(Level[Parent[Where[x]]]<Level[Parent[Where[y]]])
// swap(x,y);
// sol = max(sol,query(1,1,(int)P[Where[x]].size(),1,Level[x]-Level[Parent[Where[x]]],Pos[Where[x]]));
// x = Parent[Where[x]];
// }
if ( Level[x] > Level[y] )
swap(x,y);
sol = max(sol,query(1,1,(int)P[Where[x]].size(),Level[x]-Level[Parent[Where[x]]],Level[y]-Level[Parent[Where[x]]],Pos[Where[x]]));
cout<<sol<<'\n';
}
}
cout << "WORKING";
cin.close();
cout.close();
return 0;
}