Cod sursa(job #1414089)

Utilizator matei_cChristescu Matei matei_c Data 2 aprilie 2015 12:39:48
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.21 kb
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#include<set>
#include<map>
#include<cmath>
#include<climits>
using namespace std ;

#define maxn 100005

int N, M ;

vector<int> graf[maxn] ;

int euler[2 * maxn], nivel[2 * maxn], apare[maxn], nr ;

bool sel[maxn] ;

int m[2 * maxn][30], lg[2 * maxn] ;

void dfs(int nod, int level)
{
    sel[nod] = true ;
    euler[++nr] = nod ;
    nivel[nr] = level ;
    apare[nod] = nr ;

    for(size_t i = 0; i < graf[nod].size(); ++i)
    {
        int vecin = graf[nod][i] ;

        if( sel[vecin] == false )
        {
            dfs(vecin, level + 1) ;
            euler[++nr] = nod ;
            nivel[nr] = level ;
        }
    }
}

void precalc_logaritm()
{
    lg[1] = 0 ;

    for(int i = 2; i <= nr; ++i)
        lg[i] = lg[i / 2] + 1 ;
}

void rmq()
{
    for(int i = 1; i <= nr; ++i)
        m[i][0] = i ;

    int pas = 1 ;

    for(int j = 0; pas <= nr; ++j)
    {
        for(int i = 1; i <= nr; ++i)
        {
            if( i + pas > nr )
                m[i][j + 1] = m[i][j] ;
            else
            {
                if( nivel[ m[i][j] ] < nivel[ m[i + pas][j] ] )
                    m[i][j + 1] = m[i][j] ;
                else
                    m[i][j + 1] = m[i + pas][j] ;
            }
        }

        pas *= 2 ;
    }
}

int lca(int x, int y)
{
    if( x > y )
        swap(x, y) ;

    int dif = y - x + 1 ;
    int pas = ( 1 << lg[dif] ) ;

    if( nivel[ m[x][ lg[dif] ] ] < nivel[ m[y - pas + 1][ lg[dif] ] ] )
        return euler[ m[x][ lg[dif] ] ] ;

    return euler[ m[y - pas + 1][ lg[dif] ] ] ;
}

int main()
{
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);

    scanf("%d%d", &N, &M);

    for(int i = 1; i < N; ++i)
    {
        int x ;
        scanf("%d", &x);

        graf[x].push_back(i + 1) ;
        graf[i + 1].push_back(x) ;
    }

    dfs( 1, 0 ) ;

    precalc_logaritm() ;

    rmq() ;

    for(int i = 1; i <= M; ++i)
    {
        int x, y ;
        scanf("%d%d", &x, &y);

        printf("%d\n", lca( apare[x], apare[y] ) );
    }

	return 0 ;
}