Cod sursa(job #1936784)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 23 martie 2017 13:48:39
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.05 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");

const int NMax = 1e5 + 5;

// precalculare in O(N) si raspuns pe query in (sqrt(H))

int N,M,H,root;
int dad[NMax],depth[NMax],ancestor[NMax];
vector<int> v[NMax];
// dad[i] = tatal nodului i
// depth[i] = adancimea la care se afla nodul i in arbore
// ancestor[i] = stramosul nodului i de pe nivelul inferior al bucatelei anterioare de sqrt(H) inaltime

void dfs(int,int);
// pentru a stabili inaltimea arborelui

void build(int);
// pentru a construi vectorul ancestor

int query(int,int);
// se gaseste un LCA in O(sqrt(H)) timp

int main() {
    in>>N>>M;
    for (int i=2;i<=N;++i) {
        in>>dad[i];
        v[dad[i]].push_back(i);
    }

    dfs(1,1);

    for (root=1;root*root<=H;++root) ;
    --root;
    build(1);

    while (M--) {
        int a,b;
        in>>a>>b;

        out<<query(a,b)<<'\n';
    }

    return 0;
}

void dfs(int x,int d) {
    depth[x] = d;
    if (H < d) {
        H = d;
    }

    vector<int>::iterator it;
    for (it = v[x].begin();it < v[x].end();++it) {
        dfs(*it,d+1);
    }
}

void build(int x) {
    if (depth[x] % root == 1) {
        ancestor[x] = dad[x];
    }
    else {
        ancestor[x] = ancestor[dad[x]];
    }

    vector<int>::iterator it;
    for (it = v[x].begin();it < v[x].end();++it) {
        build(*it);
    }
}

int query(int x,int y) {
    // daca x si y nu se afla in aceeasi bucatica de sqrt(H)
    // se merge in sus de la nodul mai adanc, pe bucati de sqrt(H)
    while (ancestor[x] != ancestor[y]) {
        if (depth[x] > depth[y]) {
            x = ancestor[x];
        }
        else {
            y = ancestor[y];
        }
    }

    while (depth[x] != depth[y]) {
        if (depth[x] > depth[y]) {
            x = dad[x];
        }
        else {
            y = dad[y];
        }
    }

    while (x != y) {
        x = dad[x];
        y = dad[y];
    }

    return x;
}