Cod sursa(job #2646788)

Utilizator stefan.popescuPopescu Stefan stefan.popescu Data 2 septembrie 2020 00:10:25
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.88 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream in ("heavypath.in");
ofstream out("heavypath.out");
int n, qq, x, y, mom, tip;
vector <vector <int> > vecini;
vector <int> visIn; ///momentul vizitei initiale
vector <int> order; ///ordinea in care apar elementele in parcurgerea dfs2
vector <int> depth; ///adancimile nodurilor
vector <int> vals; ///valorile nodurilor (initiale)
vector <int> seg; ///segtree-ul
vector <int> component; ///capul lantului
vector <int> father; ///tatal fiecarui nod
vector <int> subSum; ///numarul de elemente din subarbore

void getReadingDone();

void getHLDBuilt();
void dfs1(int nod, int dad, int level);
void dfs2(int nod);
void buildSeg(int st=0, int dr=n-1, int poz=0);

void update(int pozQQ, int val, int st=0, int dr=n-1, int poz=0);
int query(int stQQ, int drQQ, int st=0, int dr=n-1, int poz=0);

inline int queryPath(int x, int y){

    int maxx=0;

    while(component[x]!=component[y]){
        if(depth[component[x]]<depth[component[y]])
            swap(x, y);
        maxx=max(maxx, query(visIn[component[x]], visIn[x]));
        x=father[component[x]];
    }
    if(depth[x]>depth[y])
        swap(x, y);
    maxx=max(maxx, query(visIn[x], visIn[y]));

    return maxx;
}

int main()
{
    getReadingDone();

    getHLDBuilt();

    while(qq--){
        in>>tip>>x>>y;
        if(tip==0){
            update(visIn[x], y);
        }
        else {
            out<<queryPath(x, y)<<"\n";
        }
    }
    return 0;
}

inline void getReadingDone(){
    in>>n>>qq;
    vals.resize(n+1);
    vecini.resize(n+1);
    for(int i=1; i<=n ; i++){
        in>>vals[i];
    }
    for(int i=1; i<n; i++){
        in>>x>>y;
        vecini[x].push_back(y);
        vecini[y].push_back(x);
    }
}


inline void getHLDBuilt(){
    subSum.resize(n+1);
    father.resize(n+1);
    depth.resize(n+1);
    dfs1(1, 0, 1);

    mom=0;
    order.resize(n+1);
    visIn.resize(n+1);
    component.resize(n+1);
    component[1]=1;
    dfs2(1);

    seg.resize(2*n+1);
    buildSeg();
}

void dfs1(int nod, int dad, int level){
    depth[nod]=level;
    father[nod]=dad;
    subSum[nod]=1;
    for(unsigned i=0; i<vecini[nod].size(); i++)
        if(vecini[nod][i]!=dad){
            dfs1(vecini[nod][i], nod, level+1);

            subSum[nod]+=subSum[vecini[nod][i]];

            if(subSum[vecini[nod][i]]>subSum[vecini[nod][0]]||vecini[nod][0]==dad)
                swap(vecini[nod][i], vecini[nod][0]);
        }
}

void dfs2(int nod){
    visIn[nod]=mom;
    order[mom]=nod;
    mom++;
    for(unsigned i=0; i<vecini[nod].size(); i++)
        if(vecini[nod][i]!=father[nod]){
            component[vecini[nod][i]]=(vecini[nod][i]==vecini[nod][0])? component[nod] : vecini[nod][i];
            dfs2(vecini[nod][i]);
        }
}

void buildSeg(int st, int dr, int poz){
    if(st==dr){
        seg[poz]=vals[order[st]];
        return;
    }
    int mij=(st+dr)/2;
    buildSeg(st, mij, poz+1);
    buildSeg(mij+1, dr, poz+2*(mij-st+1));
    seg[poz]=max(seg[poz+1], seg[poz+2*(mij-st+1)]);
}

void update(int pozQQ, int val, int st, int dr, int poz){
    if(st==dr){
        seg[poz]=val;
        return;
    }
    int mij=(st+dr)/2;
    if(pozQQ<=mij)
        update(pozQQ, val, st, mij, poz+1);
    else
        update(pozQQ, val, mij+1, dr, poz+2*(mij-st+1));
    seg[poz]=max(seg[poz+1], seg[poz+2*(mij-st+1)]);
}

int query(int stQQ, int drQQ, int st, int dr, int poz){
    if(stQQ<=st&&dr<=drQQ)
        return seg[poz];
    int mij=(st+dr)/2;
    if(stQQ<=mij&&mij+1<=drQQ)
        return max(query(stQQ, drQQ, st, mij, poz+1), query(stQQ, drQQ, mij+1, dr, poz+2*(mij-st+1)) );
    else if (stQQ<=mij)
        return query(stQQ, drQQ, st, mij, poz+1);
    else if(mij+1<=drQQ)
        return query(stQQ, drQQ, mij+1, dr, poz+2*(mij-st+1));
}