#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);
}
}
}void Update(int nod, int left, int right, int pos, int val, int decalaj)
{
if(left==right)
{
arb[nod+decalaj]=val;
return;
}
int mid = (left+right)/2;
if ( pos <= mid)
Update(2*nod,left,mid,pos,val,decalaj);
else
Update(2*nod+1,mid+1,right,pos,val,decalaj);
arb[nod+decalaj]=max(arb[2*nod+1+decalaj],arb[2*nod+decalaj]);
}
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;
}
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 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;
}