Cod sursa(job #2374420)

Utilizator DariusDCDarius Capolna DariusDC Data 7 martie 2019 18:35:27
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.51 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#define MAX 100001

using namespace std;

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

int n, m;
int N = 6;
int v[10] = {0, 3, 2, 1, 7, 4, 5, 6, 69}; //doar pt a testa rmq
vector <int> edge[MAX];

int sparse[300][20];

bool viz[MAX];
int euler[2*MAX];
int nivel[2*MAX];
int index;
int prima[MAX];

//sparse table

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

void construct()
{
    for (int i = 1; i <= index; i++)
        sparse[i][1] = i;
    for (int j = 2; (1 << (j - 1)) <= index; j++)
    {
        for (int i = 1; i + (1 << (j - 1)) - 1 <= index; 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 <= index; i++)
    {
        for (int j = 1; (1 << (j - 1)) <= n; j++)
        {
            cout << sparse[i][j] << " ";
        }
        cout << "\n";
    }*/
}

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

int lca(int low, int high)
{
    return euler[rmq(prima[low],prima[high])];
}


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 <= index; i++)
        cout << euler[i] << " ";
    cout << "\n";
    for (int i = 1; i <= index; i++)
        cout << nivel[i] << " ";
    cout << "\n";
    for (int i = 1; i <= n; i++)
    {
        cout << prima[i] << " ";
    }
    cout << "\n\n";*/
    construct();
    while (m--)
    {
        int low, high;
        fin >> low >> high;
        fout << lca(low,high) << "\n";
    }
    return 0;
}