Cod sursa(job #2029486)

Utilizator LucaSeriSeritan Luca LucaSeri Data 30 septembrie 2017 11:00:29
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.57 kb
#include <fstream>
#include <vector>
// SOLUTIA 4 - HEAVY+STRAMOSI
using namespace std;
const int MaxN = 1e5 + 1e3;

ifstream f("lca.in");
ofstream g("lca.out");

int lantdenod[MaxN], sub[MaxN], tata[MaxN], nivel_lant[MaxN], logg[MaxN], poz[MaxN], lanturi = 0, sz = 0, maxim = 0;
vector <int> gr[MaxN];
vector <int> lant[MaxN];
int dp[20][MaxN];

void dfs1(int node){
    sub[node] = 1;
    int best = 0;
    for(auto x : gr[node]){
        dfs1(x);
        sub[node] += sub[x];
        if(sub[best] < sub[x]){
            best = x;
        }
    }

    if(gr[node].size() == 0){
        lanturi ++;
        lantdenod[node] = lanturi;
        lant[lanturi].push_back(node);
        poz[node] = 0;
        return;
    }

    lantdenod[node] = lantdenod[best];
    lant[lantdenod[node]].push_back(node);
    poz[node] = lant[lantdenod[node]].size() - 1;

}

void dfs2(int node){
    if(poz[node] == lant[lantdenod[node]].size()-1){
        ++sz;
        nivel_lant[lantdenod[node]] = sz;
        maxim = max(maxim, sz);
    }
    dp[0][node] = tata[lant[lantdenod[node]].back()];
    for(auto x : gr[node]){
        dfs2(x);
    }
    if(poz[node] == lant[lantdenod[node]].size()-1){
        --sz;
    }

}

int LCA(int x, int y){
    int lx = lantdenod[x], ly = lantdenod[y];
    if(nivel_lant[lx] < nivel_lant[ly]) swap(x, y);
    lx = lantdenod[x], ly = lantdenod[y];
    int dif = nivel_lant[lx] - nivel_lant[ly];
    for(int put = logg[dif]+1; put >= 0; --put){
        if((1<<put) <= dif){
            dif -= (1<<put);
            x = dp[put][x];
        }
    }
    lx = lantdenod[x];
    if(lx == ly){
        if(poz[x] > poz[y]) return x;
        return y;
    }

    for(int put = logg[nivel_lant[lx]]+1; put >= 0; -- put){
        if((1<<put) < nivel_lant[lx] && lantdenod[dp[put][x]] != lantdenod[dp[put][y]]){
            x = dp[put][x];
            y = dp[put][y];
            lx = lantdenod[x];
        }
    }
    x = dp[0][x];
    y = dp[0][y];
    if(poz[x] > poz[y]) return x;
    return y;
}
int main(){
    int n, m;
    f >> n >> m;
    tata[1] = 0;
    for(int i = 2; i <= n; ++ i){
        int a;
        f >> a;
        tata[i] = a;
        gr[a].push_back(i);
        logg[i] = logg[i>>1]+1;
    }
    dfs1(1);
    dfs2(1);

    for(int j = 1; j <= logg[maxim] + 1; ++ j){
        for(int i = 1; i <= n; ++ i){
            dp[j][i] = dp[j-1][dp[j-1][i]];
        }
    }

    for(int i = 0; i < m; ++ i){
        int a, b;
        f >> a >> b;
        g << LCA(a, b) << '\n';
    }
    return 0;
}