Cod sursa(job #3333163)

Utilizator vladneaguVladneagu vladneagu Data 11 ianuarie 2026 16:30:17
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.09 kb
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
const int maxn = 100000 + 5;
vector<int> adj[maxn];
int n, q;
int vals[maxn];
int parent[maxn], depth[maxn];
int subtree[maxn], heavy[maxn];
int head[maxn], pos[maxn];
int cur_pos;
int seg[4 * maxn];
int binary_lift[maxn][17];
void dfs(int nod, int par) {
    parent[nod] = par;
    subtree[nod] = 1;
    heavy[nod] = -1;
    binary_lift[nod][0] = par;
    for (auto v : adj[nod]) {
        if (v == par) continue;
        depth[v] = depth[nod] + 1;
        dfs(v, nod);
        subtree[nod] += subtree[v];
        if (heavy[nod] == -1 || subtree[v] > subtree[heavy[nod]])
            heavy[nod] = v;
    }
}
void decompose(int nod, int h) {
    head[nod] = h;
    pos[nod] = ++cur_pos;
    if (heavy[nod] != -1)
        decompose(heavy[nod], h);
    for (auto v : adj[nod]) {
        if (v == parent[nod] || v == heavy[nod]) continue;
        decompose(v, v);
    }
}
void update(int nod, int l, int r, int poz, int val) {
    if (l == r) {
        seg[nod] = val;
        return;
    }
    int mid = (l + r) / 2;
    if (poz <= mid)
        update(nod * 2, l, mid, poz, val);
    else
        update(nod * 2 + 1, mid + 1, r, poz, val);
    seg[nod] = max(seg[nod * 2], seg[nod * 2 + 1]);
}
int query(int nod, int l, int r, int st, int dr) {
    if (l > dr || r < st) return 0;
    if (l >= st && r <= dr) return seg[nod];
    int mid = (l + r) / 2;
    return max(query(nod * 2, l, mid, st, dr),
               query(nod * 2 + 1, mid + 1, r, st, dr));
}
int lca(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    for (int i = 16; i >= 0; i--) {
        if (depth[binary_lift[u][i]] >= depth[v])
            u = binary_lift[u][i];
    }
    if (u == v) return u;
    for (int i = 16; i >= 0; i--) {
        if (binary_lift[u][i] != binary_lift[v][i]) {
            u = binary_lift[u][i];
            v = binary_lift[v][i];
        }
    }
    return parent[u];
}
int solve(int u, int v) {
    int ans = 0;
    while (head[u] != head[v]) {
        if (depth[head[u]] < depth[head[v]])
            swap(u, v);
        ans = max(ans, query(1, 1, n, pos[head[u]], pos[u]));
        u = parent[head[u]];
    }
    if (depth[u] > depth[v]) swap(u, v);
    ans = max(ans, query(1, 1, n, pos[u], pos[v]));
    return ans;
}
signed main() {
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
        cin >> vals[i];
    for (int i = 1; i < n; i++) {
        int a, b;
        cin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    dfs(1, 0);
    decompose(1, 1);
    for (int j = 1; j <= 16; j++) {
        for (int i = 1; i <= n; i++) {
            binary_lift[i][j] =
                binary_lift[binary_lift[i][j - 1]][j - 1];
        }
    }
    for (int i = 1; i <= n; i++)
        update(1, 1, n, pos[i], vals[i]);
    while (q--) {
        int t, x, y;
        cin >> t >> x >> y;
        if (t == 0) {
            update(1, 1, n, pos[x], y);
        } else {
            int lc = lca(x, y);
            cout << max(solve(x, lc), solve(y, lc)) << '\n';
        }
    }
    return 0;
}