Cod sursa(job #1850399)

Utilizator geo_furduifurdui geo geo_furdui Data 18 ianuarie 2017 17:22:03
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.44 kb
#include <fstream>

using namespace std;
ifstream cin ("lca.in");
ofstream cout ("lca.out");
int n,m,arb[100101],start[100010],jump[100010],sol[30][300010],viz[100010],o;
void read ()
{ int q;
    cin>>n>>m;
    for(int i=2;i<=n;i++)
    {
        cin>>q;
        arb[i]=i;
        jump[i]=start[q];
        start[q]=i;
    }
}
void dfs (int nod)
{
    sol[0][++o]=nod;
    int x=start[nod];
    while(x)
    {
        if(viz[arb[x]]==0)
        {
            viz[arb[x]]=viz[nod]+1;
            dfs(arb[x]);
            sol[0][++o]=nod;
        } x=jump[x];
    }
}
void init ()
{
    for(int i=1;i<=o;i++)
        arb[sol[0][i]]=i;
}
void construct ()
{
    int lim=0,r=1,h=1;
    while(r<=o) lim++,r*=2; r/=2; lim--;
    for(int i=1;i<=lim;++i) {
        for(int j=1;j<=o;j++)
          {
              int x1=viz[sol[i-1][j]],x2=viz[sol[i-1][j+h]];
              if(x1<x2) sol[i][j]=sol[i-1][j]; else sol[i][j]=sol[i-1][j+h];
          } h*=2; }
}
void solve_here ()
{ int a,b;
    for(int i=1;i<=m;i++)
    {
        cin>>a>>b;
        a=arb[a]; b=arb[b]; if(a>b) swap(a,b);
        int lim=0,r=1;
        while(r<=b-a+1) r*=2,lim++; lim--; r/=2;
        int x1=sol[lim][a],x2=sol[lim][b-r+1];
        if(viz[x1]<viz[x2]) cout<<x1; else cout<<x2; cout<<"\n";
    }
}
int main()
{
    read();
    dfs(1);
    init();
    construct();
    solve_here();
    cin.close();
    cout.close();
    return 0;
}