Cod sursa(job #2332751)

Utilizator DariusDCDarius Capolna DariusDC Data 31 ianuarie 2019 10:38:29
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.44 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#define MAX 100001

using namespace std;

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

int n, m;
int nivel[2*MAX-1];
int euler[2*MAX-1];
int PrimaAp[MAX];
int k;

bool viz[MAX];

vector <int> edge[MAX];

void dfs(int nod,int lvl)
{
    viz[nod] = true;
    k++;
    euler[k] = nod;
    nivel[k] = lvl;
    if (PrimaAp[nod] == 0)
        PrimaAp[nod] = k;
    for (unsigned int i = 0; i < edge[nod].size(); i++)
    {
        int vecin = edge[nod][i];
        if (!viz[vecin])
        {
            dfs(vecin,lvl+1);
            k++;
            euler[k] = nod;
            nivel[k] = lvl;
        }
    }
}

//Facem un RMQ pt vectorul PrimaAp

int sparse[2*MAX-1][45];

void ConstructSparse()
{
    for (int i = 1; i <= 2*n-1; i++)
        sparse[i][1] = i;
    for (int j = 2; (1 << (j-1)) <= 2*n-1; j++)
    {
        for (int i = 1; (i + (1 << (j-1))) <= (2*n-1) + 1; i++)
        {
            if (nivel[sparse[i][j-1]] < nivel[sparse[i + (1 << (j-2))][j-1]])
                sparse[i][j] = sparse[i][j-1];
            else
                sparse[i][j] = sparse[i + (1 << (j-2))][j-1];
        }
    }
   /* for (int i = 1; i <= 2*n-1; i++)
    {
        for (int j = 1; (1 << j) <= 2*n; j++)
                cout << sparse[i][j] << " ";
        cout << "\n";
    }*/
}

int rmq(int low,int high)
{
    int l = high - low + 1;
    int k = log2(l);
    int a = sparse[low][k];
    int b = sparse[low + l - (1 << k)][k];
    if (nivel[a] < nivel[b])
        return a;
    else
        return b;
}

int lca(int a,int b)
{
    if (a == b) //cazul trivial
        return a;
    if (b < a)

    swap(a,b);
    int x = PrimaAp[a];
    int y = PrimaAp[b];
    return euler[rmq(x,y)];
}

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

      /*  for (int i = 1; i <= 2*n-1; i++)
            cout << euler[i] << " ";
    cout << "\n";
    for (int i = 1; i <= 2*n-1; i++)
        cout << nivel[i] << " ";
    cout << "\n\n";
    for (int i = 1; i <= n; i++)
        cout << PrimaAp[i] << " ";
    cout << "\n\n\n";
*/
    ConstructSparse();
    while (m--)
    {
        int a, b;
        fin >> a >> b;
        fout << lca(a,b) << "\n";
    }
    return 0;
}