Cod sursa(job #1840091)

Utilizator xtreme77Patrick Sava xtreme77 Data 3 ianuarie 2017 19:15:07
Problema Lowest Common Ancestor Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.01 kb
// Patrick Sava
// Expected : 100

#include <bits/stdc++.h>

using namespace std ;

#define FORN(a,b,c) for(int a=b;a<=c;++a)
#define FORNBACK(a,b,c) for (int a=b;a>=c;--a)
#define mp make_pair
#define pb push_back

const int MAX = 1e5 + 14 ;
const int LG = 7 ;

vector < int > gr [ MAX ], lant [ MAX ] ;
int nrlant ;
int lantdenod[MAX] ;
int poz [MAX] ;
int sub [MAX] ;
int tata [MAX] ;

int dp [LG] [MAX] ;

void dfs ( int nod )
{
    sub [nod] = 1 ;
    int where = 0 ;
    for ( auto x : gr [nod] ) {
        tata [x] = nod ;
        dfs (x);
        sub [nod] += sub [x] ;
        if (sub [x] > sub [where] ) {
            where = x ;
        }
    }
    if (gr[nod].size()==0){
        ++ nrlant ;
        lant [nrlant].pb(nod) ;
        poz [nod] = lant [nrlant].size() - 1;
        lantdenod [nod] = nrlant ;
    }
    else {
        lant [lantdenod[where]].pb(nod) ;
        poz [nod] = lant [lantdenod[where]].size() - 1 ;
        lantdenod [nod] = lantdenod[where] ;
    }
}

int sz ;
int lvl [MAX] ;
int lg [MAX] ;
int getmax ;

void dfs2 ( int nod )
{
    if ( poz [nod] == lant [lantdenod[nod]].size() - 1 ) {
        lvl [lantdenod[nod]] = sz ;
        ++ sz ;
        getmax = max ( sz , getmax ) ;
    }
    for ( auto x : gr [nod] ) {
        dfs2(x) ;
    }

    if ( poz [nod] == lant [lantdenod[nod]].size() - 1 ) {
        -- sz ;
    }
}

int lca ( int x , int y )
{
    if ( lvl[lantdenod [x]] < lvl [lantdenod[y]] ) {
        swap (x,y) ;
    }
    int dif = lvl[lantdenod [x]] - lvl [lantdenod[y]] ;
    for ( int put = lg [dif] + 1 ; put >= 0 ; -- put ) {
        if ( dif & ( 1 << put ) ) {
            x = dp [put][x] ;
        }
    }
    if ( lantdenod [x] == lantdenod [y] ){
        if (poz[x] > poz [y]) {
            return x ;
        }
        return y ;
    }
    for ( int put = lg [lvl[lantdenod[x]]] + 1 ; put >= 0 ; -- put ){
        if ( dp [put][x] and dp [put][y] and lant[dp [put] [x]] != lant[dp [put] [y]] ) {
            x = dp [put] [x] ;
            y = dp [put] [y] ;
        }
    }
    if ( lantdenod [x] == lantdenod [y] ){
        if (poz[x] > poz [y]) {
            return x ;
        }
        return y ;
    }
    if ( poz [dp[0][x]] > poz [dp[0][y]] )  {
        return dp[0][x] ;
    }
    return dp [0][y] ;
}

int main ()
{
    freopen ("lca.in", "r", stdin) ;
    freopen ("lca.out" ,"w", stdout) ;
    int n, m;
    scanf("%d%d", &n, &m) ;
    FORN ( i , 2 , n ) {
        int x ;
        scanf("%d", &x) ;
        gr [x].pb (i) ;
        lg [i] = lg [i >> 1] + 1 ;
    }
    dfs (1) ;
    dfs2 (1) ;
    FORN ( i , 1 , n ) {
        dp [0] [i] = tata [ lant [ lantdenod [i] ].back() ] ;
    }
    for ( int j = 1 ; j <= lg [getmax] ; ++ j ) {
        for ( int i = 1 ; i <= n ; ++ i ) {
            dp [j] [i] = dp [j-1] [dp[j-1][i]] ;
        }
    }
    while (m--)
    {
        int x,y ;
        scanf("%d%d", &x, &y) ;
        printf ("%d\n" , lca(x,y)) ;
    }
    return 0 ;
}