Cod sursa(job #3357799)

Utilizator TestLicenta123Test Test TestLicenta123 Data 13 iunie 2026 15:02:22
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.25 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

struct SegmentTree {
private:
    std::vector<int> tree;
    int size;

    void update(int node, int left, int right, int pos, int value) {
        if (left == right) {
            tree[node] = value;
        } else {
            int mid = (left + right) / 2;
            if (pos <= mid) {
                update(2 * node, left, mid, pos, value);
            } else {
                update(2 * node + 1, mid + 1, right, pos, value);
            }
            tree[node] = std::max(tree[2 * node], tree[2 * node + 1]);
        }
    }

    int query(int node, int left, int right, int start, int end) {
        if (start > end || left > right) return 0;
        if (start <= left && right <= end) return tree[node];
        if (end < left || right < start) return 0;
        int mid = (left + right) / 2;
        int left_val = query(2 * node, left, mid, start, end);
        int right_val = query(2 * node + 1, mid + 1, right, start, end);
        return std::max(left_val, right_val);
    }

public:
    explicit SegmentTree(int n) : size(n) {
        tree.resize(4 * n);
    }

    void update(int pos, int value) {
        update(1, 1, size, pos, value);
    }

    int query(int start, int end) {
        if (start > end) std::swap(start, end);
        return query(1, 1, size, start, end);
    }
};

struct Graph {
    std::vector<std::vector<int>> adj;
    std::vector<int> value;
    std::vector<int> parent, depth, heavy, pos, subtree;
    int ptr = 0;
    SegmentTree tree;

    explicit Graph(std::vector<int>& values) : value(values), tree(values.size() - 1) {
        int n = values.size() - 1;
        adj.resize(n + 1);
        parent.resize(n + 1);
        depth.resize(n + 1);
        heavy.assign(n + 1, -1);
        pos.resize(n + 1);
        subtree.resize(n + 1);
    }

    void add_edge(int x, int y) {
        adj[x].push_back(y);
        adj[y].push_back(x);
    }

    int dfs(int node, int par) {
        parent[node] = par;
        subtree[node] = 1;
        int max_subtree = 0;
        for (int child : adj[node]) {
            if (child != par) {
                depth[child] = depth[node] + 1;
                int child_subtree = dfs(child, node);
                subtree[node] += child_subtree;
                if (child_subtree > max_subtree) {
                    max_subtree = child_subtree;
                    heavy[node] = child;
                }
            }
        }
        return subtree[node];
    }

    void decompose(int node, int head) {
        pos[node] = ++ptr;
        tree.update(ptr, value[node]);
        if (heavy[node] != -1) {
            decompose(heavy[node], head);
        }
        for (int child : adj[node]) {
            if (child != parent[node] && child != heavy[node]) {
                decompose(child, child);
            }
        }
    }

    void heavy_light() {
        dfs(1, -1);
        decompose(1, 1);
    }

    void update(int node, int val) {
        tree.update(pos[node], val);
    }

    int query_path(int u, int v) {
        int result = 0;
        for (; pos[u] != pos[v]; v = parent[heavy[v]]) {
            if (depth[heavy[v]] > depth[heavy[u]]) std::swap(u, v);
            if (heavy[u] != -1 && depth[heavy[u]] >= depth[v]) {
                result = std::max(result, tree.query(pos[heavy[u]], pos[u]));
                u = parent[heavy[u]];
            } else {
                result = std::max(result, tree.query(pos[v], pos[v]));
                v = parent[v];
            }
        }
        if (depth[u] > depth[v]) std::swap(u, v);
        result = std::max(result, tree.query(pos[u], pos[v]));
        return result;
    }
};

int main() {
    std::ifstream input("heavypath.in");
    std::ofstream output("heavypath.out");

    int n, q;
    input >> n >> q;
    std::vector<int> values(n + 1);
    for (int i = 1; i <= n; ++i) {
        input >> values[i];
    }

    Graph graph(values);
    for (int i = 0; i < n - 1; ++i) {
        int x, y;
        input >> x >> y;
        graph.add_edge(x, y);
    }

    graph.heavy_light();

    while (q--) {
        int type, x, y;
        input >> type >> x >> y;
        if (type == 0) {
            graph.update(x, y);
        } else {
            output << graph.query_path(x, y) << '\n';
        }
    }

    return 0;
}