Cod sursa(job #2100003)

Utilizator Alex18maiAlex Enache Alex18mai Data 4 ianuarie 2018 23:24:57
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.21 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream cin ("lca.in");
ofstream cout ("lca.out");

int dp[20][100100];
int LOG[100100];

vector < vector < int > > gr(100100);
vector < int > dad (100100);
vector < int > G (100100);
vector < int > lv (100100);

int cont = 0;
vector < vector < int > > chain(100100);
vector < int > CHAIN(100100);
vector < int > NR(100100);
vector < int > LV(100100);

vector < vector < int > > GR(100100);

void dfs (int root){

    lv[root] = lv[dad[root]] + 1;

    int MAX = 0;
    int go = 0;
    G[root] = 1;

    for (auto &x : gr[root]){
        dfs(x);
        if (MAX < G[x]){
            MAX = G[x];
            go = x;
        }
        G[root] += G[x];
    }

    if (go == 0){
        cont ++;
        chain[cont].push_back(root);
        CHAIN[root] = cont;
        NR[root] = 0;
    }
    else{
        chain[CHAIN[go]].push_back(root);
        CHAIN[root] = CHAIN[go];
        NR[root] = chain[CHAIN[root]].size() - 1;
        for (auto &x : gr[root]){
            if (x == go){
                continue;
            }
            GR[CHAIN[root]].push_back(CHAIN[x]);
        }
    }

}

void DFS(int root){

    for (auto &x : GR[root]){
        LV[x] = LV[root] + 1;
        dp[0][x] = root;
        DFS(x);
    }

}

int main() {

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    //stramosi pe hpd

    int n , m;
    cin>>n>>m;

    for (int i=2; i<=n; i++){
        LOG[i] = LOG[i/2] + 1;
    }

    for (int i=2; i<=n; i++){
        cin>>dad[i];
        gr[dad[i]].push_back(i);
    }

    dfs(1);

    /*cout<<cont<<'\n';
    for (int i=1; i<=cont; i++){
        for (auto &x : chain[i]){
            cout<<x<<" ";
        }
        cout<<'\n';
    }
    cout<<'\n';*/

    DFS(CHAIN[1]);

    for (int bit=1; bit <= LOG[n]; bit++){
        for (int i=1; i<=n; i++){
            dp[bit][i] = dp[bit-1][dp[bit-1][i]];
        }
    }

    for (int i=1; i<=m; i++){
        int x , y;
        cin>>x>>y;
        int cx = CHAIN[x];
        int cy = CHAIN[y];

        int pos;
        //cout<<LV[cx]<<" "<<LV[cy]<<'\n';
        if (LV[cx] > LV[cy]){
            pos = LV[cx] - LV[cy] - 1;
            while (pos){
                cx = dp[LOG[pos]][cx];
                pos -= (1 << LOG[pos]);
            }
            x = dad[chain[cx][chain[cx].size()-1]];
            cx = dp[0][cx];
        }
        if (LV[cy] > LV[cx]){
            pos = LV[cy] - LV[cx] - 1;
            while (pos){
                cy = dp[LOG[pos]][cy];
                pos -= (1 << LOG[pos]);
            }
            y = dad[chain[cy][chain[cy].size()-1]];
            cy = dp[0][cy];
        }

        if (cx == cy){
            if (NR[x] > NR[y]){
                cout<<x<<'\n';
            }
            else{
                cout<<y<<'\n';
            }
            continue;
        }

        for (int bit = LOG[LV[cx]]; bit >=0; bit--){
            if (dp[bit][cx] != dp[bit][cy]){
                cx = dp[bit][cx];
                cy = dp[bit][cy];
            }
        }

        x = dad[chain[cx][chain[cx].size()-1]];
        y = dad[chain[cy][chain[cy].size()-1]];

        if (NR[x] > NR[y]){
            cout<<x<<'\n';
        }
        else{
            cout<<y<<'\n';
        }

    }

    return 0;
}