Cod sursa(job #2453833)

Utilizator andreisontea01Andrei Sontea andreisontea01 Data 6 septembrie 2019 11:07:32
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.4 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 100005;

int n, m, lanturi;
vector<int> graf[MAXN], hpd[MAXN];
int v[MAXN], tata[MAXN], nivelLant[MAXN], lant[MAXN], pos[MAXN], sub[MAXN];
int dp[MAXN][30], lg[MAXN];

void HPD_init(int nod){
    sub[nod] = 1;
    for(auto x:graf[nod]){
        HPD_init(x);
        sub[nod] += sub[x];
    }
    if(sub[nod] == 1){
        lanturi++;
        hpd[lanturi].push_back(nod);
        lant[nod] = lanturi;
        return;
    }
    int best = 0;
    for(auto x:graf[nod]){
        if(sub[best] < sub[x])
            best = x;
    }
    lant[nod] = lant[best];
    hpd[lant[best]].push_back(nod);
    pos[nod] = (int)hpd[lant[best]].size() - 1;
}

int niv;

void StramosiInit(int nod){
    if(pos[nod] == 0){
        niv++;
        nivelLant[lant[nod]] = niv;
    }
    dp[nod][0] = tata[hpd[lant[nod]][0]];
    for(auto x:graf[nod])
        StramosiInit(x);
    if(pos[nod] == 0) niv--;
}

int solve(int x, int y){
    int lx = lant[x], ly = lant[y];
    if(nivelLant[lx] < nivelLant[ly]){
        swap(x, y);
        swap(lx, ly);
    }
    int dif = nivelLant[lx] - nivelLant[ly];
    for(int p = lg[dif] + 1; p >= 0; --p){
        if((1 << p) <= dif){
            dif -= (1 << p);
            x = dp[x][p];
        }
    }
    lx = lant[x];
    if(lx == ly){
        if(pos[x] < pos[y]) return x;
        return y;
    }
    for(int p = lg[nivelLant[lx]] + 1; p >= 0; --p){
        if(nivelLant[lx] > (1 << p) && lant[dp[x][p]] != lant[dp[y][p]]){
            x = dp[x][p];
            y = dp[y][p];
            lx = lant[x];
        }
    }
    x = dp[x][0];
    y = dp[y][0];
    if(pos[x] < pos[y]) return x;
    return y;
}

int main()
{
    ifstream fin("lca.in");
    ofstream fout("lca.out");
    fin >> n >> m;
    for(int i = 2; i <= n; ++i){
        fin >> tata[i];
        graf[tata[i]].push_back(i);
        lg[i] = lg[i / 2] + 1;
    }
    HPD_init(1);
    for(int i = 1; i <= lanturi; ++i) reverse(hpd[i].begin(), hpd[i].end());
    for(int i = 1; i <= n; ++i) pos[i] = (int)hpd[lant[i]].size() - 1 - pos[i];
    StramosiInit(1);
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= 20; ++j)
            dp[i][j] = dp[dp[i][j - 1]][j - 1];
    }
    while(m){
        int x, y;
        fin >> x >> y;
        fout << solve(x, y) << "\n";
        m--;
    }
    return 0;
}