Cod sursa(job #1042906)

Utilizator Dddarius95Darius-Florentin Neatu Dddarius95 Data 27 noiembrie 2013 19:43:26
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.08 kb
#include <vector>
#include <fstream>
#define Nmax 100099
#define Lmax 20
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");

int N,M;
int E[2*Nmax],First[Nmax],Level[2*Nmax]; //parcurgere Euler
int lg[2*Nmax],RMQ[Lmax][2*Nmax]; //RMQ

vector < int > Arb[Nmax];

inline void ReadInput()
{
    f>>N>>M;
    for(int i=2;i<=N;++i)
    {
        int x;
        f>>x;
        Arb[x].push_back(i);
    }
}

void DFS(int nod, int nivel)
{
    E[++E[0]]=nod; //nodul actual este adaugat in reprezentarea Euler a arborelui
    Level[E[0]]=nivel; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui
    First[nod]=E[0]; //se retine si prima aparitie a fiecarui nod in reprezentarea Euler a arborelui

    vector < int > :: iterator it;
    for(it=Arb[nod].begin();it!=Arb[nod].end();++it)
    {
        DFS(*it,nivel+1);
        E[++E[0]]=nod;
        Level[E[0]]=nivel;
    }
}

void Make_RMQ()
{
    //in Rmq[i][j] va fi nodul de nivel minim
    //dintre pozitiile (j, j + 2^i - 1) din reprezentarea Euler a arborelui
    for(int i=2;i<=E[0];++i)lg[i]=lg[i/2]+1;

    for(int j=1;j<=E[0];++j)RMQ[0][j]=j;

    for(int i=1; (1<<i)<=E[0]; ++i)
      for(int j=1; j<=E[0]-(1<<i); ++j)
        {
            int nivel=(1<<(i-1));
            RMQ[i][j]=RMQ[i-1][j];
            if( Level[ RMQ[i-1][j+nivel] ] < Level[ RMQ[i][j]] ) RMQ[i][j]=RMQ[i-1][j+nivel];
        }
}

int LCA(int x, int y)
{
    //LCA-ul nodurilor x si y va fi nodul
    //cu nivel minim din secventa (First[x], First[y]) din reprezentarea Euler a arborelui
    int left=First[x],right=First[y];
    if(left>right)swap(left,right);
    int diff=right-left+1;
    int log=lg[diff];
    int sol=RMQ[log][left];
    int sh=diff-(1<<log);
    if(Level[ sol ] > Level[ RMQ[log][left+sh] ])sol=RMQ[log][left+sh];
    return E[sol];
}


int main()
{
    ReadInput();
    DFS(1,0); // Arbore cu radacina in 1 (radacina are nivel 0)
    Make_RMQ();
    for(int i=1;i<=M;++i)
    {
        int x,y;
        f>>x>>y;
        g<<LCA(x,y)<<'\n';
    }
    return 0;
}