Cod sursa(job #1851414)

Utilizator saba_alexSabadus Alex saba_alex Data 19 ianuarie 2017 18:45:08
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.75 kb
#include <iostream>
#include <fstream>
#include <vector>
#define MAX 100005

using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");

int euler[2*MAX],nivel[2*MAX],apar[MAX];
int n,m,e,log[2*MAX];
int rmq[20][2*MAX];
vector <int> G[MAX];

void dfs(int nod, int lvl){/// fac si reprezentarea euler

    e++;
    euler[e]=nod;
    nivel[e]=lvl;
    apar[nod]=e;
    for(auto it: G[nod]){

        dfs(it,lvl+1);
        e++;
        euler[e]=nod;
        nivel[e]=lvl;
    }
}


void build_rmq(){///rmq with a twist, am poziti in rmq, dar compar nivelurile elementelor aflate pe acele pozitii

    /// in loc de 1<<k<=3 pot folosi k<=log[e]
    log[0]=-1;
    for(int i=1;i<=e;++i)
        log[i]=1+log[i/2];

    for(int i=1; i<=e; ++i)
        rmq[0][i]=i;

    for(int k=1; k<=log[e]; ++k)
        for(int i=1; i+(1<<k)-1<=e; ++i){
            rmq[k][i]=rmq[k-1][i];
            if(nivel[rmq[k-1][i+(1<<(k-1))]] < nivel[rmq[k][i]])
                rmq[k][i]=rmq[k-1][i+(1<<(k-1))];
        }
}

int query(int x, int y){

    x=apar[x];
    y=apar[y];
    if(x>y)
        swap(x,y);
    int l=log[y-x+1];
    int sol=rmq[l][x];
    if(nivel[sol] > nivel[rmq[l][y-(1<<l)+1]])
        sol=rmq[l][y-(1<<l)+1];
    return euler[sol];
}

int main()
{
    fin>>n>>m;
    for(int i=2, x; i<=n; ++i){
        fin>>x;
        G[x].push_back(i);
    }

    nivel[1]=0;
    dfs(1,0);

    /* Ca sa vad daca ii reprezentarea euleriana buna
    for(int i=1;i<=e;++i)
        cout<<euler[i]<<' ';
    cout<<'\n';
    for(int i=1;i<=e;++i)
        cout<<nivel[i]<<' ';*/

    build_rmq();

    int x,y;
    for(int i=1; i<=m; ++i){
        fin>>x>>y;
        fout<<query(x,y)<<'\n';
    }
    return 0;
}