Cod sursa(job #1060845)

Utilizator classiusCobuz Andrei classius Data 18 decembrie 2013 20:27:38
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.98 kb
// 10.12.2013
// Lowest Common Ancestor
// <O(N logN)> Pre-processing time
// <O(logN)> Query time
// I create the matrix M[1..N][0..logH] where M[i][j] represents the 2^j-th ancestor
// of node i

using namespace std;

#include<fstream>
#include<cmath>
#include<vector>
#include<algorithm>

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

const int MAXN=100001;

vector<int> v[MAXN]; // v[i][j] will point to the j-th son of node i
int A[MAXN]; // A[i] will point to the father of i
int L[MAXN]; // L[i] will have the level of node i
int M[MAXN][30];
int H;

void dfs(int i){
    for(unsigned j=0;j<v[i].size();j++){
        L[v[i][j]]=L[i]+1;
        dfs(v[i][j]);
    }
    return;
}

int main(){
    int N,Q;

    cin>>N>>Q;

    for(int i=2;i<=N;i++){
        cin>>A[i];
        v[A[i]].push_back(i);
    }

    // I will assume that the root of the tree is node 1
    L[1]=1;
    dfs(1); //for setting the level of each node and calculating the depth of the tree
    H=*max_element(L+1,L+N+1);

    for(int i=1;i<=N;i++)
        M[i][0]=A[i]; //base case, the ancestor directly above this node

    for(int j=1;(1<<j)<=H;j++)
        for(int i=1;i<=N;i++)
            if(M[M[i][j-1]][j-1])
                M[i][j]=M[M[i][j-1]][j-1];

    // The query Part

    while(Q--){
        int x,y;
        cin>>x>>y;

        // First to get the nodes on the same level

        if(L[x]>L[y]){
            int lv=L[x]-L[y];
            for(int j=0;(1<<j)<=lv;j++)
                if(lv & (1<<j))
                    x=M[x][j];

        }else if(L[y]>L[x]){
            int lv=L[y]-L[x];
            for(int j=0;(1<<j)<=lv;j++)
                if(lv & (1<<j))
                    y=M[y][j];
        }

        // Now I use binary search to get the LCA
        while(true){
            int s=0;
            while(M[x][s]!=M[y][s])
                s++;
            if(!s) break;
            s--;
            x=M[x][s];
            y=M[y][s];
        }

        cout<<( x==y ? x : M[x][0])<<'\n';
    }

    return 0;
}