#include <fstream>
#include <vector>
using namespace std;
ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");
int n, m, tip, x, y;
int poz_cnt;
int v[100005];
int sz[100005], t[100005], heavy[100005];
int top[100005], h[100005], poz[100005];
int aint[400005];
vector <int> g[100005];
void dfs(int nod, int tata = 0) {
sz[nod] = 1;
t[nod] = tata;
h[nod] = h[tata] + 1;
int mx = 0;
for(auto &fiu : g[nod]) {
if(fiu != tata) {
dfs(fiu, nod);
sz[nod] += sz[fiu];
if(sz[fiu] > mx)
mx = sz[fiu], heavy[nod] = fiu;
}
}
}
void build(int nod, int par) {
top[nod] = par, poz[nod] = ++poz_cnt;
if(heavy[nod])
build(heavy[nod], par);
for(auto &fiu : g[nod]) {
if(fiu != t[nod] && fiu != heavy[nod])
build(fiu, fiu);
}
}
void update(int nod, int st, int dr, int ind, int val) {
if(ind < st || dr < ind)
return;
if(st == dr) {
aint[nod] += val;
return;
}
int mid = (st + dr) >> 1;
update((nod << 1), st, mid, ind, val);
update((nod << 1) | 1, mid + 1, dr, ind, val);
aint[nod] = max(aint[(nod << 1)], aint[(nod << 1) | 1]);
}
int query(int nod, int st, int dr, int l, int r) {
if(r < st || dr < l || st > dr)
return 0;
if(l <= st && dr <= r)
return aint[nod];
int mid = (st + dr) >> 1;
return max(query((nod << 1), st, mid, l, r), query((nod << 1) | 1, mid + 1, dr, l, r));
}
int solve(int x, int y) {
int ans = 0;
while(top[x] != top[y]) {
if(h[top[x]] > h[top[y]])
swap(x, y);
ans = max(ans, query(1, 1, n, poz[top[y]], poz[y]));
y = t[top[y]];
}
if(h[x] > h[y])
swap(x, y);
ans = max(ans, query(1, 1, n, poz[x], poz[y]));
return ans;
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> v[i];
for(int i = 1; i < n; i++) {
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1);
build(1, 1);
for(int i = 1; i <= n; i++)
update(1, 1, n, poz[i], v[i]);
for(; m; m--) {
cin >> tip >> x >> y;
if(tip == 0) {
update(1, 1, n, poz[x], y - v[x]);
v[x] = y;
} else {
cout << solve(x, y) << '\n';
}
}
return 0;
}