#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <queue>
using namespace std;
int n, m, i, j, k, val[100001], pathnum[100001], pathpos[100001], heavy[100001], dad[100001], height[100001], vf;
vector<int> graph[100001], pathlist[100001];
class Tree{
public:
int *v, sz;
void change(int a, int b, int pos, int ch, int position);
int get(int a, int b, int left, int right, int position);
void update(int pos, int ch){
change(1, sz, pos, ch, 1);
}
int query(int left, int right){
return get(1, sz, left, right, 1);
}
void setsize(int sz){
this->sz=sz;
v=(int *)realloc(v, (4*sz+10)*sizeof(int));
return;
}
}tree[100005];
queue<int> q;
void findheavy(int node);
void dfs(int node);
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d%d", &n, &m);
for(i=1; i<=n; ++i) scanf("%d", &val[i]);
height[0]=-1;
for(i=2; i<=n; ++i){
int x, y;
scanf("%d%d", &x, &y);
graph[x].push_back(y);
graph[y].push_back(x);
}
findheavy(1);
q.push(1);
while(!q.empty()){++vf; pathlist[vf].push_back(dad[q.front()]); dfs(q.front()); q.pop();}
for(i=1; i<=vf; ++i){
tree[i].setsize(pathlist[i].size()-1);
for(j=1; j<=tree[i].sz; ++j) tree[i].update(j, val[pathlist[i][j]]);
}
for(i=1; i<=m; ++i){
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
if(!t) tree[pathnum[x]].update(pathpos[x], y);
else{
int sol=-1;
while(pathnum[x]!=pathnum[y]){
if(height[pathlist[pathnum[x]][0]]<height[pathlist[pathnum[y]][0]]) swap(x, y);
sol=max(sol, tree[pathnum[x]].query(1, pathpos[x]));
x=pathlist[pathnum[x]][0];
}
if(height[x]<height[y]) swap(x, y);
sol=max(sol, tree[pathnum[x]].query(pathpos[y], pathpos[x]));
printf("%d\n", sol);
}
}
return 0;
}
void Tree::change(int a, int b, int pos, int ch, int position){
int mid=(a+b)/2;
if(a==b) {v[position]=ch; return;}
if(pos<=mid) change(a, mid, pos, ch, 2*position);
else change(mid+1, b, pos, ch, 2*position+1);
v[position]=max(v[2*position], v[2*position+1]);
return;
}
int Tree::get(int a, int b, int left, int right, int position){
int mid=(a+b)/2;
if(a==left && b==right) return v[position];
if(right<=mid) return get(a, mid, left, right, 2*position);
else if(left>mid) return get(mid+1, b, left, right, 2*position+1);
else return max(get(a, mid, left, mid, 2*position), get(mid+1, b, mid+1, right, 2*position+1));
}
void findheavy(int node){
++heavy[node];
for(auto i:graph[node]) if(i!=dad[node]){
dad[i]=node; height[i]=height[node]+1;
findheavy(i);
heavy[node]+=heavy[i];
}
return;
}
void dfs(int node){
pathpos[node]=pathlist[vf].size();
pathnum[node]=vf;
pathlist[vf].push_back(node);
int next=0, mx=-1;
for(auto i:graph[node]){
if(i!=dad[node] && heavy[i]>mx){
mx=heavy[i];
next=i;
}
}
for(auto i:graph[node]) if(i!=dad[node] && i!=next) q.push(i);
if(next)dfs(next);
}