Cod sursa(job #2082644)

Utilizator gundorfMoldovan George gundorf Data 6 decembrie 2017 17:21:43
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.55 kb
#include <iostream>
#include <fstream>
#define Nmax 100005
#define LogMaxN 17
#include <queue>
#include <math.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");

queue <int> a[Nmax],b[Nmax];
int n,m; // numarul de noduri si nr de intrebari
int nivel[Nmax];// stochez nivelul pe care se afla nodul i
int viz[Nmax];// vector pentru stabilirea nivelelor fiecarui nod
int matrice[Nmax][LogMaxN]; // matrice folosita la precalculare rmq
int prima_aparitie[Nmax];

void Citire (int &n,int &m,queue <int> a[Nmax])
{
    int i,x;
    fin>>n>>m;
    for (i = 2 ; i <= n ; i++)
    {
        fin>>x;
        a[x].push(i);
        b[x].push(i);
    }
}

void Reprezentare_Euler (int x,queue <int> a[Nmax],int reprez_Euler[],int &k) // asemenea unei parcurgeri rsd doar ca afisez radacina si pe intoarcere
{
    int i;

    k++ ;
    reprez_Euler[k]=x ;

    while ( !a[x].empty() )
    {
        int y = a[x].front() ;
        a[x].pop();
        Reprezentare_Euler(y,a,reprez_Euler,k) ;
        k++ ;
        reprez_Euler[k]=x ;
    }

}

void Stabilire_nivel_nod (int x,int tata,int nivel[],queue<int> a[Nmax],int viz[])
{
    int i;
    nivel[x]=nivel[tata]+1;
    viz[x]=1;
    while (!a[x].empty())
    {
        int y=a[x].front();
        a[x].pop();
        if (viz[y]==0)
            Stabilire_nivel_nod(y,x,nivel,a,viz);
    }

}
void Initializare_Prima_Aparitie (int euler[],int k,int prima_aparitie[])
{
    int i;
    for (i=1; i<=n; i++)
        viz[i]=0;
    for (i=1; i<=k; i++)
        if (viz[euler[i]]==0)
        {
            prima_aparitie[euler[i]]=i;
            viz[euler[i]]=1;
        }
}

int nivel_min (int a,int b,int nivel[])
{
    if (nivel[a]<nivel[b]) return a;
    return b;
}
void precalculare_RMQ (int RMQ[Nmax][LogMaxN],int nivel[],int pozitie_e,int euler[])
{
    for(unsigned int i=1; i<pozitie_e; i++)
    {
        RMQ[i][0]=euler[i];
    }
    for(unsigned int i=1; (1<<i)<=pozitie_e; i++)
    {
        for(unsigned int j=0; (1<<i)+j<pozitie_e; j++)
        {
            RMQ[j][i]=nivel_min(RMQ[j][i-1],RMQ[j+(1<<(i-1))][i-1],nivel);
        }
    }
}
/*
int logaritm (int x)
{
    int nr=1;
    while (1<<nr<=x) nr++;

    nr--;

    return nr;
}
*/
int query_RMQ (int a,int b,int nivel[],int RMQ[Nmax][LogMaxN])
{
    int diferenta = b-a+1 ;
    int k=(int)log2(diferenta);
    int rest=diferenta-(1<<k);
    return nivel_min( RMQ[a][k] , RMQ[a+rest][k] , nivel ) ;

}
int main()
{
    int Parcurgere_Euler [5*Nmax],k=0, i ;

    Citire( n, m,a ) ;

    Reprezentare_Euler(1, a, Parcurgere_Euler, k ) ;   ///stabilesc parcurgerea euler

    nivel[0]=-1;
    Stabilire_nivel_nod(1, 0, nivel, b, viz ) ;     ///precalculez nivelul pe care se afla fiecare nod si stochez in vectorul nivel

     precalculare_RMQ(matrice,nivel,k,Parcurgere_Euler);

    Initializare_Prima_Aparitie(Parcurgere_Euler, k, prima_aparitie); /// stochez in vectorul prima aparitie pozitia la care apare prima data un nod in parcurgerea euler
/*
    for (i=1;i<=k;i++)
        fout<<i<<" ";
    fout<<"\n";
    for (i=1 ; i <= k ; i++ )
        fout<<Parcurgere_Euler[i]<<" ";

    fout<<"\n";

    for (i=1; i<=k; i++)
        fout<<nivel[Parcurgere_Euler[i]]<<" ";
     fout<<"\n";
*/
    for (i=1; i<=m; i++)
    {
        int a,b,mini,maxi;
        fin>>a>>b;
        mini=min(prima_aparitie[a],prima_aparitie[b]);
        maxi=max(prima_aparitie[a],prima_aparitie[b]);
        fout<<query_RMQ(mini,maxi,nivel,matrice)<<"\n";
    }

    return 0;
}