Cod sursa(job #1967637)

Utilizator Laura_CorneiLaura Maria Cornei Laura_Cornei Data 16 aprilie 2017 21:20:02
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 2.27 kb
#include <stdint.h>
#include <fstream>
#include <math.h>
#define nmax 100001
#define mmax 2000001
#define log2l 18
#define sqrtn 450
using namespace std;
fstream f1("lca.in", ios::in);
fstream f2("lca.out", ios::out);
int32_t n, m, t[nmax], ha[nmax*2], eu[nmax*2], nr, first[nmax], lung;
int32_t  a[2*nmax][log2l+1];
int32_t put2[log2l+1];
///first[i]= indicele primei aparitii a nodului i in parcurgerea euler (eu)
///lca(x,y)= nodul din eu care este cuprins intre first[x] si first[y] si are ha[i] minim
///a[i][j]= minimul din vect ha, care incepe de pe pozitia i si contine 2^j elemente
void citire()
{
    int32_t  i;
    f1>>n>>m;
    for(i=2; i<=n; i++)
        f1>>t[i];
    ///1= radacina
}
int32_t minim(int32_t a, int32_t b)
{
    if(a<b) return a;
    else return b;
}
int32_t query(int32_t l, int32_t r)
{
    int32_t j=log2(r-l+1), v1, v2;
    v1=a[l][j];
    v2=a[r-put2[j]+1][j];
    if(ha[v1]<ha[v2]) return v1;
    else return v2;
    ///a[l][j] aproape echivalent cu a[r-pow(2, j)+1][j]
    ///le folosesti pe amandoua pt a det minimul cu exactitate (pierderi la log2)
}
void afisare()
{
    int32_t i, x, y, a, b;
    for(i=1; i<=m; i++)
    {
        f1>>x>>y;
        a=first[x];
        b=first[y];
        if(a>b) swap(a, b);

        f2<<eu[query(a, b)]<<"\n";///minim intervalul a,b
        ///lca(x,y);
    }
}
void euler(int32_t rad, int32_t h)
{
    int32_t i;
    nr++;
    eu[nr]=rad;
    ha[nr]=h;

    for(i=1; i<=n; i++)
        if(t[i]==rad)
    {
        euler(i, h+1);

        nr++;
        eu[nr]=rad;
        ha[nr]=h;
    }
}
void first_v()
{
    int32_t i;
    lung=2*n-1;
    for(i=1; i<=lung; i++)
        if(!first[eu[i]])  first[eu[i]]=i;
}
void rmq()
{
    int32_t i, j;
    for(i=1; i<=lung; i++)
        a[i][0]=i;
    for(j=1; j<=log2l; j++)
        for(i=1; i<=(lung-put2[j]); i++)
             if(ha[a[i][j-1]] < ha[a[i+put2[j-1]][j-1]]) a[i][j]=a[i][j-1];
             else a[i][j]=a[i+put2[j-1]][j-1];
}
void putere()
{
    int32_t i;
    put2[0]=1;
    put2[1]=2;
    for(i=2; i<=log2l; i++)
        put2[i]=put2[i-1]*2;
}
int main()
{
    citire();
    euler(1, 0);
    first_v();
    putere();
    rmq();///range minimum query
    afisare();
    return 0;
}