Cod sursa(job #2374614)

Utilizator DariusDCDarius Capolna DariusDC Data 7 martie 2019 19:37:50
Problema Lowest Common Ancestor Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.43 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#define MAX 100005

using namespace std;

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

int n, m;
vector <int> edge[MAX];

int sparse[MAX][25];

bool viz[MAX];
int euler[2*MAX + 1];
int nivel[2*MAX + 1];
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 (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)
{
    if (low == high)
        return low;
    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;
}