Cod sursa(job #3272726)

Utilizator AnSeDraAndrei Sebastian Dragulescu AnSeDra Data 30 ianuarie 2025 19:47:34
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.39 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int Nmax = 100005;

struct nod{
    int val;
    int adancime;
    int marime_subarbore;
    int parinte;
    int capat_lant;
    int fiu_heavy;
    int timp_procesare;
    vector<int> vecini;
};

int n, q, timp;
int ordine_liniarizare[Nmax];
nod arbore[Nmax];
int aint[4 * Nmax];

void aint_build(int nod, int st, int dr){
    if(st == dr){
        aint[nod] = arbore[ordine_liniarizare[st]].val;
        return;
    }

    int mid = (st + dr) / 2;

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

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

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

    int mid = (st + dr) / 2;

    if(poz <= mid){
        aint_update(2 * nod, st, mid, poz, val);
    }
    else{
        aint_update(2 * nod + 1, mid + 1, dr, poz, val);
    }
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}

int aint_query(int nod, int st, int dr, int poz_st, int poz_dr){
    if(poz_st > poz_dr){
        swap(poz_st, poz_dr);
    }

    if(st == poz_st && dr == poz_dr){
        return aint[nod];
    }

    int mid = (st + dr) / 2;

    if(poz_dr <= mid){
        return aint_query(2 * nod, st, mid, poz_st, poz_dr);
    }
    else if(mid < poz_st){
        return aint_query(2 * nod + 1, mid + 1, dr, poz_st, poz_dr);
    }
    else{
        return max(aint_query(2 * nod, st, mid, poz_st, mid), aint_query(2 * nod + 1, mid + 1, dr, mid + 1, poz_dr));
    }
}

void citire_arbore(){
    int nod1, nod2;

    fin >> n >> q;

    for(int i = 1; i <= n; i++){
        fin >> arbore[i].val;
    }

    for(int i = 1; i < n; i++){
        fin >> nod1 >> nod2;
        arbore[nod1].vecini.push_back(nod2);
        arbore[nod2].vecini.push_back(nod1);
    }
}

void dfs_adancimi(int nod, int parinte){
    arbore[nod].parinte = parinte;
    arbore[nod].fiu_heavy = 0;
    arbore[nod].marime_subarbore = 1;
    arbore[nod].adancime = arbore[parinte].adancime + 1;

    for(int vecin : arbore[nod].vecini){
        if(vecin != parinte){
            dfs_adancimi(vecin, nod);

            arbore[nod].marime_subarbore += arbore[vecin].marime_subarbore;
            if(arbore[arbore[nod].fiu_heavy].marime_subarbore < arbore[vecin].marime_subarbore){
                arbore[nod].fiu_heavy = vecin;
            }
        }
    }
}

void dfs_liniarizare(int nod, int capat_lant){
    arbore[nod].timp_procesare = ++timp;
    arbore[nod].capat_lant = capat_lant;
    ordine_liniarizare[timp] = nod;

    if(arbore[nod].fiu_heavy){
        dfs_liniarizare(arbore[nod].fiu_heavy, capat_lant);
    }

    for(int vecin : arbore[nod].vecini){
        if(vecin != arbore[nod].parinte && vecin != arbore[nod].fiu_heavy){
            dfs_liniarizare(vecin, vecin);
        }
    }
}

void initializare_hld(){
    dfs_adancimi(1, 0);

    timp = 0;
    dfs_liniarizare(1, 1);
    aint_build(1, 1, n);
}

void hld_update(int poz, int val){
    arbore[poz].val = val;
    aint_update(1, 1, n, arbore[poz].timp_procesare, val);
}

int hld_query(int st, int dr){
    int capat_st, capat_dr;

    capat_st = arbore[st].capat_lant;
    capat_dr = arbore[dr].capat_lant;

    if(capat_st == capat_dr){
        return aint_query(1, 1, n, arbore[st].timp_procesare, arbore[dr].timp_procesare);
    }
    else if(arbore[capat_st].adancime > arbore[capat_dr].adancime){
        return max(aint_query(1, 1, n, arbore[st].timp_procesare, arbore[capat_st].timp_procesare), hld_query(arbore[capat_st].parinte, dr));
    }
    else{
        return max(aint_query(1, 1, n, arbore[dr].timp_procesare, arbore[capat_dr].timp_procesare), hld_query(st, arbore[capat_dr].parinte));
    }
}

void citire_si_rezolvare_interogari(){
    int tip, poz, val, capat_st, capat_dr;

    for(int i = 1; i <= q; i++){
        fin >> tip;

        if(tip == 0){
            fin >> poz >> val;
            hld_update(poz, val);
        }
        else{
            fin >> capat_st >> capat_dr;
            fout << hld_query(capat_st, capat_dr) << '\n';
        }
    }
}

int main(){
    citire_arbore();
    initializare_hld();
    citire_si_rezolvare_interogari();

    return 0;
}