Cod sursa(job #1790442)

Utilizator cristian.caldareaCaldarea Cristian Daniel cristian.caldarea Data 28 octombrie 2016 11:28:26
Problema Lowest Common Ancestor Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 1.66 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

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

const int Nmax = 100002;

vector<vector<int>> G;

int n, m, nr, x, y;
int a[2*Nmax], lg[2*Nmax], niv[2*Nmax], fp[Nmax], r[2*Nmax][20];

void Read();
void Dfs(int x, int nv);
void Rmq();
int Lca(int x, int y);

int main()
{
    Read();

    for(int i = 2; i < 2 * Nmax; i++)
        lg[i] = lg[i / 2] + 1;

    Dfs(1, 1);
    Rmq();

    for(int i = 1; i <= m; i++)
    {
        fin >> x >> y;
        fout << Lca(x, y) << "\n";
    }

    fin.close();
    fout.close();
    return 0;
}
void Read()
{
    fin >> n >> m;

    G = vector<vector<int>>(n+1);


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

}
void Dfs(int x, int nv)
{

    a[++nr] = x;
    niv[nr] = nv;
    fp[x] = nr;
    for (auto y : G[x])
    {
        Dfs(y, nv + 1);
        a[++nr] = x;
        niv[nr] = nv;
    }
}

void Rmq()
{
    int N = 2 * n - 1;

    for (int i = 1; i <= N; i++)
        r[i][0] = i;

    for(int j = 1; (1 << j) <= N; j++)
        for(int i = 1; i + (1 << j) < N; i++)
        {
            if ( niv[r[i][j - 1]] < niv[r[i + (1 << (j - 1))][j - 1]] )
                r[i][j] = r[i][j - 1];
            else
                r[i][j] = r[i + (1 << (j - 1))][j - 1];
        }
}

int Lca(int x, int y)
{
    int px = fp[x], py = fp[y];

    if ( px > py )
        swap(px, py);

    int k = lg[py - px  + 1];

    if ( niv[r[px][k]] < niv[r[py - (1 << k) + 1][k]])
        return a[r[px][k]];
    return a[r[py - (1 << k) + 1][k]];
}