Cod sursa(job #3284493)

Utilizator AdrianRosuRosu Adrian Andrei AdrianRosu Data 11 martie 2025 18:10:35
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.88 kb
#include <bits/stdc++.h>
#define DIM 200001

using namespace std;

ifstream fin("heavypath.in");

ofstream fout("heavypath.out");

int father[DIM], sz[DIM], depth[DIM], chain_idx[DIM], chain_pos[DIM], chain_size[DIM], tin[DIM], tout[DIM], leaf[DIM], v[DIM];

int RMQ[int32_t(log2(DIM)) + 1][DIM];

vector <int> G[DIM];

struct nod{

    int answer, ret;

};

vector < vector <nod> > wmt;

vector <int> pos[DIM];

int t, Q, n, task, x, y, total_chains, i, j, lca;

void dfs(int node, int dad){

    father[node] = dad;

    depth[node] = depth[father[node]] + 1;

    sz[node] = 1;

    tin[node] = ++t;

    for(auto k : G[node])

        if(k != dad){

            dfs(k, node);

            sz[node] += sz[k];

        }

    if(G[node].size() == 1 && node != 1)

        leaf[node] = true;

    tout[node] = ++t;

}

void build_chains(int node, int idx){

    chain_idx[node] = idx;

    chain_pos[node] = ++chain_size[chain_idx[node]];

    pos[idx].push_back(node);

    if(leaf[node])

        return ; // am ajuns la capatul lantului

    int ret = 0;

    for(auto k : G[node])

        if(k != father[node] && (!ret || sz[k] > sz[ret]))

            ret = k;

    // continui lantul asta cu ret

    for(auto k : G[node])

        if(k != father[node] && k != ret) // cel mai greu lant (Maciuca / Costinel)

            build_chains(k, ++total_chains);

    build_chains(ret, idx);



}

nod Combine(nod st, nod dr){

    nod answer;

    if(st.answer >= dr.answer)

        answer = st;

    else answer = dr;

    return answer;

}

void Build_Tree(int state, int node, int st, int dr){

    if(st == dr) {

        wmt[state][node].answer = v[pos[state][st - 1]];

        wmt[state][node].ret = st;

    }

    else {

        int mij = (st + dr) >> 1;

        Build_Tree(state, node << 1, st, mij);

        Build_Tree(state, node << 1 | 1, mij + 1, dr);

        wmt[state][node] = Combine(wmt[state][node << 1], wmt[state][node << 1 | 1]);

    }

}

void Update(int state, int node, int st, int dr, int a, int b){

    if(st == dr)

        wmt[state][node].answer = b;

    else {

        int mij = (st + dr) >> 1;

        if(a <= mij)

            Update(state, node << 1, st, mij, a, b);

        else Update(state, node << 1 | 1, mij + 1, dr, a, b);

        wmt[state][node] = Combine(wmt[state][node << 1], wmt[state][node << 1 | 1]);

    }

}

nod Query(int state, int node, int st, int dr, int a, int b){

    if(dr < a || st > b)

        return {0, 0};

    if(st >= a && dr <= b)

        return wmt[state][node];

    else {

        int mij = (st + dr) >> 1;

        nod ok1 = Query(state, node << 1, st, mij, a, b);

        nod ok2 = Query(state, node << 1 | 1, mij + 1, dr, a, b);

        return Combine(ok1, ok2);

    }



}

int get_ancestor(int n, int k){

    for(int bit=20;bit>=0;bit--)

        if((k >> bit) & 1)

            n = RMQ[bit][n];

    return n;

}

bool is_ancestor(int x, int y){

    if(tin[x] <= tin[y] && tout[y] <= tout[x])

        return true;

    return false;

}

int LCA(int x, int y){

    int st = 0, dr = depth[x] - 1;

    int ret = x;

    while(st <= dr){

        int mij = (st + dr) >> 1;

        if(is_ancestor(get_ancestor(x, mij), y)){

            ret = mij;

            dr = mij - 1;

        }

        else st = mij + 1;

    }

    return get_ancestor(x, ret);

}

int solve(int start, int finish){

    int ret = 0;

    while(chain_idx[start] != chain_idx[finish]){

        ret = max(ret, Query(chain_idx[start], 1, 1, chain_size[chain_idx[start]], 1, chain_pos[start]).answer);

        start = father[pos[chain_idx[start]][0]];

    }

    ret = max(ret, Query(chain_idx[start], 1, 1, chain_size[chain_idx[start]], chain_pos[finish], chain_pos[start]).answer);

    return ret;

}

int main(){

    fin >> n >> Q;

    for(i=1;i<=n;i++)

        fin >> v[i];

    for(i=2;i<=n;i++){

        fin >> x >> y;

        G[x].push_back(y);

        G[y].push_back(x);

    }

    dfs(1, 0);

    total_chains = 1;

    build_chains(1, 1);

    wmt.resize(total_chains + 5);

    for(i=1;i<=total_chains;i++)

        wmt[i].resize(4 * ( chain_size[i] + 5) );

    for(i=1;i<=total_chains;i++)

        Build_Tree(i, 1, 1, chain_size[i]);

    return 0;

    for(i=1;i<=n;i++)

        RMQ[0][i] = father[i];

    for(i=1;(1<<i)<=n;i++)

        for(j=1;j<=n;j++)

            RMQ[i][j] = RMQ[i - 1][RMQ[i - 1][j]];

    while(Q--){

        fin >> task >> x >> y;

        if(task == 0)

            Update(chain_idx[x], 1, 1, chain_size[chain_idx[x]], chain_pos[x], y);

        else {

            lca = LCA(x, y);

            fout << max(solve(x, lca), solve(y, lca)) << "\n";

        }

    }


}