Cod sursa(job #2329697)

Utilizator DariusDCDarius Capolna DariusDC Data 27 ianuarie 2019 12:10:21
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.48 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#define MAX 100001

using namespace std;

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

vector <int> edge[MAX];

int n, m;
//radacin este 1
int k;
bool viz[MAX];
int euler[2*MAX-1]; //parcurgerea euleriana
int level[2*MAX-1]; //nivelul fiecarul element din euler
int fai[MAX]; // prima aparitire a fiecarui nod in euler;

//pentru rmq
int sparse[MAX][20];

void construct()
{
    for (int i = 0; i < 2*n-1; i++)
        sparse[i][0] = i+1;
    for (int j = 1; (1 << j) <= 2*n-1; j++)
    {
        for (int i = 0; (i + (1 << j) - 1) < 2*n-1; i++)
        {
            if (level[sparse[i][j-1]] < level[sparse[i+ (1 << (j-1))][j-1]])
                sparse[i][j] = sparse[i][j-1];
            else
                sparse[i][j] = sparse[i+(1 << (j-1))][j-1];
            //sparse[i][j] = min(level[sparse[i][j-1]],level[sparse[i+(1 << (j-1))][j-1]]);
        }
    }

    /*for (int i = 0; i < 2*n-1; i++)
    {
        for (int j = 0; j < log2(2*n-1); j++)
            cout << sparse[i][j] << " ";
        cout << "\n";
    }
    cout << "\n";*/
}

int rmq(int low,int high)
{
    low--;
    high--;
    int l = (high - low + 1);
    int k = log2(l);
    return min(sparse[low][k],sparse[high - (1 << k) + 1][k]);
}

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

int lca(int a,int b)
{
    if (a == b) //cazul trivial
        return a;
    if (fai[a] > fai[b])
        swap(a,b);
    return euler[rmq(fai[a],fai[b])];
}

int main()
{
    fin >> n >> m;
    for (int i = 1; i < n; i++)
    {
        int x;
        fin >> x;
        edge[i+1].push_back(x);
        edge[x].push_back(i+1);
    }
    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 << level[i] << " ";
    cout << "\n";
    for (int i = 1; i <= n;++i)
        cout << fai[i] << " ";*/
    construct();
    while (m--)
    {
        int a, b;
        fin >> a >> b;
        fout << lca(a,b) << "\n";
    }

    return 0;
}