Cod sursa(job #1168690)

Utilizator mirceadinoMircea Popoveniuc mirceadino Data 9 aprilie 2014 11:47:47
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.86 kb
#include<cstdio>
#include<vector>
#include<algorithm>

using namespace std;

const int NMAX = 100000+5;
const int LMAX = 18;

void Read(),Precompute(),Solve();

int N,M,Cnt;
int Father[NMAX];
vector<int> Graph[NMAX];
int RMQ[LMAX][2*NMAX];
int Euler[2*NMAX];
int First[NMAX];
int Depth[NMAX];

void DFS(int node,int depth)
{
    vector<int>::iterator it;

    Depth[node] = depth;
    Euler[++Cnt] = node;
    First[node] = Cnt;

    for(it = Graph[node].begin(); it != Graph[node].end(); it++)
        if(!Depth[*it])
        {
            DFS(*it,depth+1);
            Euler[++Cnt] = node;
        }
}

void Build_RMQ()
{
    int i,p,step;

    for(i = 1; i <= Cnt; i++)
        RMQ[0][i] = i;

    for(step = 1, p = 2; p <= Cnt; step++, p <<= 1)
        for(i = 1; i + (p>>1) <= Cnt; i++)
            if(Depth[Euler[RMQ[step-1][i]]] <= Depth[Euler[RMQ[step-1][i + (p>>1)]]]) RMQ[step][i] = RMQ[step-1][i];
            else RMQ[step][i] = RMQ[step-1][i + (p>>1)];
}

int Query(int x,int y)
{
    int dist = y - x + 1,step,p;
    for(step = 0, p = 1; p <= dist; step++, p <<= 1);
    step--;
    p >>= 1;
    if(Depth[Euler[RMQ[step][x]]] <= Depth[Euler[RMQ[step][y-p+1]]]) return Euler[RMQ[step][x]];
    else return Euler[RMQ[step][y-p+1]];
}

int main()
{
    Read();
    Precompute();
    Solve();

    return 0;
}

void Read()
{
    int i;

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

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

    for(i = 2; i <= N; i++)
    {
        scanf("%d",&Father[i]);
        Graph[Father[i]].push_back(i);
    }
}

void Precompute()
{
    DFS(1,1);
    Build_RMQ();
}

void Solve()
{
    int x,y;

    for(; M; --M)
    {
        scanf("%d%d",&x,&y);
        x = First[x];
        y = First[y];
        if(x>y) swap(x,y);
        printf("%d\n",Query(x,y));
    }
}