Cod sursa(job #1808863)

Utilizator AdrianGotcaAdrian Gotca AdrianGotca Data 18 noiembrie 2016 11:49:36
Problema Lowest Common Ancestor Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 1.67 kb
#include <bits/stdc++.h>

using namespace std;

int n,m,t[100005],viz[100005],pe[200005],niv[200005],npe,first[100005],NODE[200005][20],NIV[200005][20];
vector <int> G[100005];
int lca(int,int);
void DFS(int,int);
void rmq();
int main(){
    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);
    cin>>n>>m;
    for (int i=2;i<=n;i++){
        cin>>t[i];
        G[i].push_back(t[i]);
        G[t[i]].push_back(i);
    }
    DFS(1,0);
    rmq();
    for (int i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        cout<<lca(a,b)<<'\n';
    }
}

void DFS(int node,int level){
    viz[node]=1;
    pe[++npe]=node;
    niv[npe]=level;
    if (!first[node]){
        first[node]=npe;
    }
    for (int i=0;i<G[node].size();i++){
        int child=G[node][i];
        if (!viz[child]){
            DFS(child,level+1);
            pe[++npe]=node;
            niv[npe]=level;
        }
    }
}

void rmq(){
    for (int i=1;i<=npe;i++){
        NIV[i][0]=niv[i];
        NODE[i][0]=pe[i];
    }
    for (int j=1;(1<<j)<=npe;j++){
        for (int i=1;i+(1<<(j-1))<=npe;i++){
            if (NIV[i][j-1]<=NIV[i+(1<<(j-1))][j-1]){
                NIV[i][j]=NIV[i][j-1];
                NODE[i][j]=NODE[i][j-1];
            }
            else {
                NIV[i][j]=NIV[i+(1<<(j-1))][j-1];
                NODE[i][j]=NODE[i+(1<<(j-1))][j-1];
            }
        }
    }
}

int lca(int a,int b){
    a=first[a];
    b=first[b];
    if (b<a){
        swap(a,b);
    }
    int l=b-a+1;
    int lg=log2(l);
    if (NIV[a][lg]>NIV[b-(1<<lg)+1][lg]){
        return NODE[b-(1<<lg)+1][lg];
    }
    return NODE[a][lg];
}