#include <bits/stdc++.h>
using namespace std;

using ll = long long;
static const ll NEG = -(1LL << 60);

struct Mat {
    ll a[2][2];
};

struct SegTree {
    int n;
    vector<Mat> st;
    vector<ll> *val;
    vector<int> *rev;

    static Mat mergeMat(const Mat &L, const Mat &R) {
        Mat C;
        for (int i = 0; i < 2; ++i)
            for (int j = 0; j < 2; ++j)
                C.a[i][j] = NEG;

        for (int lf = 0; lf < 2; ++lf) {
            for (int llv = 0; llv < 2; ++llv) {
                if (L.a[lf][llv] == NEG) continue;
                for (int rf = 0; rf < 2; ++rf) {
                    if (R.a[rf][0] == NEG && R.a[rf][1] == NEG) continue;
                    if (llv == 1 && rf == 1) continue;
                    for (int rl = 0; rl < 2; ++rl) {
                        if (R.a[rf][rl] == NEG) continue;
                        C.a[lf][rl] = max(C.a[lf][rl], L.a[lf][llv] + R.a[rf][rl]);
                    }
                }
            }
        }
        return C;
    }

    static Mat leaf(ll x) {
        Mat m;
        for (int i = 0; i < 2; ++i)
            for (int j = 0; j < 2; ++j)
                m.a[i][j] = NEG;
        m.a[0][0] = 0;
        m.a[1][1] = x;
        return m;
    }

    void build(int idx, int l, int r) {
        if (l == r) {
            st[idx] = leaf((*val)[(*rev)[l]]);
            return;
        }
        int mid = (l + r) >> 1;
        build(idx << 1, l, mid);
        build(idx << 1 | 1, mid + 1, r);
        st[idx] = mergeMat(st[idx << 1], st[idx << 1 | 1]);
    }

    SegTree() {}
    SegTree(int n, vector<ll> *val, vector<int> *rev) : n(n), val(val), rev(rev) {
        st.resize(4 * n + 5);
        build(1, 1, n);
    }

    void update(int idx, int l, int r, int pos) {
        if (l == r) {
            st[idx] = leaf((*val)[(*rev)[l]]);
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) update(idx << 1, l, mid, pos);
        else update(idx << 1 | 1, mid + 1, r, pos);
        st[idx] = mergeMat(st[idx << 1], st[idx << 1 | 1]);
    }

    Mat query(int idx, int l, int r, int ql, int qr) {
        if (qr < l || r < ql) {
            Mat bad;
            for (int i = 0; i < 2; ++i)
                for (int j = 0; j < 2; ++j)
                    bad.a[i][j] = NEG;
            return bad;
        }
        if (ql <= l && r <= qr) return st[idx];
        int mid = (l + r) >> 1;
        Mat L = query(idx << 1, l, mid, ql, qr);
        Mat R = query(idx << 1 | 1, mid + 1, r, ql, qr);

        if (L.a[0][0] == NEG && L.a[0][1] == NEG && L.a[1][0] == NEG && L.a[1][1] == NEG) return R;
        if (R.a[0][0] == NEG && R.a[0][1] == NEG && R.a[1][0] == NEG && R.a[1][1] == NEG) return L;
        return mergeMat(L, R);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, q;
    cin >> n >> q;

    vector<ll> a(n + 1);
    for (int i = 1; i <= n; ++i) cin >> a[i];

    vector<vector<int>> g(n + 1);
    for (int i = 1; i <= n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    vector<int> parent(n + 1, 0), depth(n + 1, 0), heavy(n + 1, -1), sz(n + 1, 0);
    vector<int> order;
    order.reserve(n);

    stack<int> st;
    st.push(1);
    parent[1] = 0;
    depth[1] = 0;

    while (!st.empty()) {
        int u = st.top();
        st.pop();
        order.push_back(u);
        for (int v : g[u]) {
            if (v == parent[u]) continue;
            parent[v] = u;
            depth[v] = depth[u] + 1;
            st.push(v);
        }
    }

    for (int i = n - 1; i >= 0; --i) {
        int u = order[i];
        sz[u] = 1;
        int best = -1;
        for (int v : g[u]) {
            if (v == parent[u]) continue;
            sz[u] += sz[v];
            if (best == -1 || sz[v] > sz[best]) best = v;
        }
        heavy[u] = best;
    }

    vector<int> head(n + 1, 0), pos(n + 1, 0), rev(n + 1, 0);
    int cur = 0;
    vector<pair<int,int>> chains;
    chains.push_back({1, 1});

    while (!chains.empty()) {
        auto [u, h] = chains.back();
        chains.pop_back();

        for (int v = u; v != -1; v = heavy[v]) {
            head[v] = h;
            pos[v] = ++cur;
            rev[cur] = v;

            for (int to : g[v]) {
                if (to == parent[v] || to == heavy[v]) continue;
                chains.push_back({to, to});
            }
        }
    }

    SegTree seg(cur, &a, &rev);

    auto revMat = [&](const Mat &m) {
        Mat t;
        t.a[0][0] = m.a[0][0];
        t.a[0][1] = m.a[1][0];
        t.a[1][0] = m.a[0][1];
        t.a[1][1] = m.a[1][1];
        return t;
    };

    auto queryRange = [&](int l, int r) {
        return seg.query(1, 1, cur, l, r);
    };

    auto pathQuery = [&](int u, int v) {
        vector<Mat> rightParts;
        Mat ans;
        bool has = false;

        while (head[u] != head[v]) {
            if (depth[head[u]] >= depth[head[v]]) {
                Mat curMat = queryRange(pos[head[u]], pos[u]);
                curMat = revMat(curMat);
                if (!has) {
                    ans = curMat;
                    has = true;
                } else {
                    ans = SegTree::mergeMat(ans, curMat);
                }
                u = parent[head[u]];
            } else {
                Mat curMat = queryRange(pos[head[v]], pos[v]);
                rightParts.push_back(curMat);
                v = parent[head[v]];
            }
        }

        if (depth[u] >= depth[v]) {
            Mat curMat = queryRange(pos[v], pos[u]);
            curMat = revMat(curMat);
            if (!has) {
                ans = curMat;
                has = true;
            } else {
                ans = SegTree::mergeMat(ans, curMat);
            }
        } else {
            Mat curMat = queryRange(pos[u], pos[v]);
            rightParts.push_back(curMat);
        }

        for (int i = (int)rightParts.size() - 1; i >= 0; --i) {
            if (!has) {
                ans = rightParts[i];
                has = true;
            } else {
                ans = SegTree::mergeMat(ans, rightParts[i]);
            }
        }

        ll best = 0;
        for (int i = 0; i < 2; ++i)
            for (int j = 0; j < 2; ++j)
                best = max(best, ans.a[i][j]);
        return best;
    };

    while (q--) {
        int type;
        cin >> type;
        if (type == 1) {
            int x;
            ll y;
            cin >> x >> y;
            a[x] = y;
            seg.update(1, 1, cur, pos[x]);
        } else {
            int u, v;
            cin >> u >> v;
            cout << pathQuery(u, v) << '\n';
        }
    }

    return 0;
}
