Cod sursa(job #3195191)

Utilizator AdrianRosuRosu Adrian Andrei AdrianRosu Data 20 ianuarie 2024 11:15:47
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.25 kb
#include <bits/stdc++.h>
#define DIM 100001
#define time eiuhf

using namespace std;

ifstream fin("heavypath.in");

ofstream fout("heavypath.out");

vector <int> G[DIM];

int wmt[4 * DIM];

int v[DIM], wmt_pos[DIM], father[DIM], depth[DIM], nodes[DIM], heavy_path[DIM], pos[DIM], chain[DIM], leader[DIM];

int time, n, i, m, Q, x, y, nr_chain, task;

void Build(int node, int st, int dr){

    if(st == dr)

        wmt[node] = v[wmt_pos[st]];

    else {


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

        Build(node << 1, st, mij);

        Build(node << 1 | 1, mij + 1, dr);

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


    }

}

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

    if(st == dr)

        wmt[node] = b;

    else {

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

        if(a <= mij)

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

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

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

    }

}

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

    if(dr < a || st > b)

        return 0;

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

        return wmt[node];

    else {

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

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

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

        return max(ok1, ok2);

    }

}

void dfs(int node, int mother){

    father[node] = mother;

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

    nodes[node] = 1;

    for(auto k : G[node]){

        if(!depth[k]){

            dfs(k, node);

            if(nodes[heavy_path[node]] < nodes[k])

                heavy_path[node] = k;

            nodes[node] += nodes[k];

        }

    }

}


void decompose(int node, int mother){

    ++time;

    wmt_pos[time] = node;

    pos[node] = time;

    if(heavy_path[mother] != node){

        ++nr_chain;

        leader[nr_chain] = node;

        chain[node] = nr_chain;

    }

    else chain[node] = chain[mother];

    if(heavy_path[node])

        decompose(heavy_path[node], node);

    for(auto k : G[node])

        if(k != mother && k != heavy_path[node])

            decompose(k, node);

}

int solve(int x, int y){

    int answer = 0;

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

        if(depth[leader[chain[x]]] < depth[leader[chain[y]]]){


            answer = max(answer, Query(1, 1, n, pos[leader[chain[y]]], pos[y]));

            y = father[leader[chain[y]]];


        }

        else {

            answer = max(answer, Query(1, 1, n, pos[leader[chain[x]]], pos[x]));

            x = father[leader[chain[x]]];


        }


    }

    answer = max(answer, Query(1, 1, n, min(pos[x], pos[y]), max(pos[x], pos[y])));

    return answer;

}

int main(){

    fin >> n >> Q;

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

        fin >> v[i];

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

        fin >> x >> y;

        G[x].push_back(y);

        G[y].push_back(x);

    }

    dfs(1, 0);

    decompose(1, 0);

    Build(1, 1, n);

    while(Q--){

        fin >> task >> x >> y;

        if(task == 0)

            Update(1, 1, n, pos[x], y);

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

    }

}