Cod sursa(job #3173141)

Utilizator AnSeDraAndrei Sebastian Dragulescu AnSeDra Data 21 noiembrie 2023 21:56:13
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.45 kb
#include <fstream>
#include <vector>

using namespace std;

const int Nmax = 100005;

int n, m, sol;
int numar_lanturi;

struct arbore{
    int val;
    int nivel;
    int indice_lant;
    int pozitie_aint;
    int greutate;
    vector<int> sons;
};

struct heavy{
    vector<int> lant;
    vector<int> aint;
    int parinte = 0;

    void build_aint(int nod, int st, int dr){
        if(st == dr){
            aint[nod] = lant[st];
            return;
        }

        int mid = (st + dr) / 2;

        build_aint(2 * nod, st, mid);
        build_aint(2 * nod + 1, mid + 1, dr);

        aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
    }

    void update_aint(int nod, int st, int dr, int poz, int val){
        if(st == dr && st == poz){
            aint[nod] = val;
            return;
        }

        int mid = (st + dr) / 2;

        if(poz <= mid){
            update_aint(2 * nod, st, mid, poz, val);
        }
        else{
            update_aint(2 * nod + 1, mid + 1, dr, poz, val);
        }

        aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
    }

    int query_aint(int nod, int st, int dr, int a, int b){
        if(st == a && dr == b){
            return aint[nod];
        }

        int mid = (st + dr) / 2;

        if(b <= mid){
            return query_aint(2 * nod, st, mid, a, b);
        }
        else if(mid < a){
            return query_aint(2 * nod + 1, mid + 1, dr, a, b);
        }
        else{
            return max(query_aint(2 * nod, st, mid, a, mid), query_aint(2 * nod + 1, mid + 1, dr, mid + 1, b));
        }
    }
};

arbore arb[Nmax];
heavy lanturi[Nmax];

void build_heavy(int nod, int nivel){
    arb[nod].nivel = nivel;

    if(arb[nod].sons.size() == 0){
        lanturi[++numar_lanturi].lant.push_back(arb[nod].val);

        arb[nod].greutate = 1;
        arb[nod].indice_lant = numar_lanturi;
        arb[nod].pozitie_aint = 0;

        return;
    }

    int greutate_max = 0, indice = -1;

    for(int son : arb[nod].sons){
        build_heavy(son, nivel + 1);

        if(arb[son].greutate > greutate_max){
            indice = son;
            greutate_max = arb[son].greutate;
        }
    }

    arb[nod].greutate = 1;
    for(int son : arb[nod].sons){
        arb[nod].greutate += arb[son].greutate;

        if(son != indice){
            lanturi[arb[son].indice_lant].parinte = nod;
        }
        else{
            lanturi[arb[son].indice_lant].lant.push_back(arb[nod].val);

            arb[nod].indice_lant = arb[son].indice_lant;
            arb[nod].pozitie_aint = lanturi[arb[son].indice_lant].lant.size() - 1;
        }
    }
}

void build_lanturi(){
    for(int i = 1; i <= numar_lanturi; i++){
        lanturi[i].aint.resize(4 * lanturi[i].lant.size());

        lanturi[i].build_aint(1, 0, lanturi[i].lant.size() - 1);
    }
}

void query(int a, int b){
    if(arb[a].indice_lant == arb[b].indice_lant){
        sol = max(sol, lanturi[arb[a].indice_lant].query_aint(1, 0, lanturi[arb[a].indice_lant].lant.size() - 1, min(arb[a].pozitie_aint, arb[b].pozitie_aint), max(arb[a].pozitie_aint, arb[b].pozitie_aint)));
        return;
    }

    if(arb[lanturi[arb[a].indice_lant].parinte].nivel < arb[lanturi[arb[b].indice_lant].parinte].nivel){
        swap(a, b);
    }

    sol = max(sol, lanturi[arb[a].indice_lant].query_aint(1, 0, lanturi[arb[a].indice_lant].lant.size() - 1, arb[a].pozitie_aint, lanturi[arb[a].indice_lant].lant.size() - 1));

    query(lanturi[arb[a].indice_lant].parinte, b);
}

int main()
{
    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");

    int a, b, poz, val;
    bool type;

    fin >> n >> m;

    for(int i = 1; i <= n; i++){
        fin >> arb[i].val;
    }
    for(int i = 1; i <= n - 1; i++){
        fin >> a >> b;

        if(a > b){
            swap(a, b);
        }

        arb[a].sons.push_back(b);
    }

    numar_lanturi = 0;
    build_heavy(1, 1);

    build_lanturi();

    for(int i = 1; i <= m; i++){
        fin >> type;

        if(type){
            fin >> a >> b;

            sol = 0;
            query(a, b);

            fout << sol << '\n';
        }
        else{
            fin >> poz >> val;

            arb[poz].val = val;

            lanturi[arb[poz].indice_lant].update_aint(1, 0, lanturi[arb[poz].indice_lant].lant.size() - 1, arb[poz].pozitie_aint, val);
        }
    }

    return 0;
}