Cod sursa(job #3360255)

Utilizator BeilandArnoldArnold Beiland BeilandArnold Data 11 iulie 2026 09:20:38
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.08 kb
// vezi: https://cp-algorithms.com/graph/hld.html
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

// returns size of subtree
int dfs(int v, const vector<vector<int>> &adj,
        vector<int> &parent, vector<int> &depth, vector<int> &heavy);

void decompose(int v, int h,
        const vector<vector<int>> &adj, const vector<int> &parent,
        vector<int> &heavy, vector<int> &head, vector<int> &pos,
        int &curr_aint_pos);

void segtree_update(int index, int left, int right, int pos, int val,
                    vector<int> &tree);

int segtree_query(int index, int left, int right, int qleft, int qright,
                  const vector<int> &tree);

int query(int x, int y, int n,
          const vector<int> &head, const vector<int> &pos,
          const vector<int> &depth, const vector<int> &parent,
          const vector<int> &segtree);

int main()
{
    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");
    //ifstream fin("input.txt");
    //ofstream fout("output.txt");

    int n, m;
    fin >> n >> m;

    vector<int> v(n+1);
    for (int i = 1; i <= n; i++)
        fin >> v[i];

    vector<vector<int>> adj(n+1);
    for (int i = 1; i <= n-1; i++) {
        int a, b;
        fin >> a >> b;

        adj[a].push_back(b);
        adj[b].push_back(a);
    }

    vector<int> parent(n+1, 0);
    parent[1] = 1; // rădăcina

    vector<int> depth(n+1, 0); // adâncimea în arbore
    vector<int> heavy(n+1, -1); // copilul care e legat
                                // cu heavy edge
    vector<int> head(n+1, -1); // cel mai de sus nod
                               // din lanțul nodului
    vector<int> segtree(4*n + 10, 0); // arbint
    vector<int> pos(n+1); // poziția nodului în arbint

    dfs(1, adj, parent, depth, heavy);

    int curr_aint_pos = 1;
    decompose(1, 1, adj, parent, heavy, head, pos, curr_aint_pos);

    for (int i = 1; i <= n; i++)
        segtree_update(1, 1, n, pos[i], v[i], segtree);

    /*for (int i = 1; i <= n; i++)
        fout << head[i] << " " << pos[i] << endl;
    fout << "--------------\n";*/

    for (int i = 0; i < m; i++) {
        int t, x, y;
        fin >> t >> x >> y;

        if (t == 0) {
            v[x] = y;
            segtree_update(1, 1, n, pos[x], v[x], segtree);
        }
        else {
            int res = query(x, y, n, head, pos, depth, parent, segtree);
            fout << res << endl;
        }
    }

    return 0;
}


int dfs(int v, const vector<vector<int>> &adj,
        vector<int> &parent, vector<int> &depth, vector<int> &heavy)
{
    int v_size = 1;
    int max_child_size = 0;

    for (int c : adj[v]) {
        if (c != parent[v]) {
            parent[c] = v;
            depth[c] = depth[v] + 1;
            int c_size = dfs(c, adj, parent, depth, heavy);
            v_size += c_size;
            if (c_size > max_child_size) {
                max_child_size = c_size;
                heavy[v] = c;
            }

        }
    }

    return v_size;
}


void decompose(int v, int h,
        const vector<vector<int>> &adj, const vector<int> &parent,
        vector<int> &heavy, vector<int> &head, vector<int> &pos,
        int &curr_aint_pos)
{
    head[v] = h;
    pos[v] = curr_aint_pos;
    curr_aint_pos++;

    if (heavy[v] != -1) {
        decompose(heavy[v], h,
                adj, parent, heavy, head, pos, curr_aint_pos);
    }

    for (int c : adj[v]) {
        if (c != parent[v] && c != heavy[v]) {
            decompose(c, c,
                adj, parent, heavy, head, pos, curr_aint_pos);
        }
    }
}


int query(int x, int y, int n,
          const vector<int> &head, const vector<int> &pos,
          const vector<int> &depth, const vector<int> &parent,
          const vector<int> &segtree)
{
    int res = 0;

    while (head[x] != head[y]) {

        if (depth[head[x]] > depth[head[y]])
            swap(x, y);

        int path_max = segtree_query(1, 1, n,
                                     pos[head[y]], pos[y], segtree);

        if (path_max > res)
            res = path_max;

        y = parent[head[y]];
    }

    if (depth[x] > depth[y])
        swap(x, y);

    int last_path = segtree_query(1, 1, n, pos[x], pos[y], segtree);
    if (last_path > res)
        res = last_path;

    return res;
}

void segtree_update(int index, int left, int right, int pos, int val,
                    vector<int> &tree)
{
    if (pos > right || pos < left)
        return;

    if (left == right) {
        tree[index] = val;
        return;
    }

    int mid = (left + right) / 2;
    segtree_update(2*index, left, mid, pos, val, tree);
    segtree_update(2*index+1, mid+1, right, pos, val, tree);

    tree[index] = max(tree[2*index], tree[2*index+1]);
}

int segtree_query(int index, int left, int right, int qleft, int qright,
                  const vector<int> &tree)
{
    if (qleft > right || qright < left)
        return -1;

    if (qleft <= left && qright >= right)
        return tree[index];

    int mid = (left + right) / 2;
    int r1 = segtree_query(2*index, left, mid, qleft, qright, tree);
    int r2 = segtree_query(2*index+1, mid+1, right, qleft, qright, tree);

    return max(r1, r2);
}