Cod sursa(job #1690571)

Utilizator BugirosRobert Bugiros Data 15 aprilie 2016 11:54:38
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2 kb
#include <fstream>
#include <vector>
using namespace std;

const int MAXN = 100005;

const int MAXP = 20;

const int MAXEULER = MAXN * 2;//fiecare nod apare in jur de doua ori in reprezentare

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

int n;
vector<int> fii[MAXN];

int rmq[MAXP][MAXEULER * 2];//cel mai mic numar din intervalul j, j + 2 ^ i - 1
int lmax[MAXEULER];

int euler[MAXEULER], nivel[MAXEULER], primul[MAXN];

int l_euler = 0;

void citire()
{
    int tata;
    for (int i = 2;i <= n;++i)
    {
        in >> tata;
        fii[tata].push_back(i);
    }
}

void dfs(int nod, int niv)
{
    ++l_euler;
    euler[l_euler] = nod;
    nivel[l_euler] = niv;
    primul[nod] = l_euler;

    for (unsigned int i = 0; i < fii[nod].size();++i)
    {
        dfs(fii[nod][i], niv + 1);
        ++l_euler;
        euler[l_euler] = nod;
        nivel[l_euler] = niv;
    }
}

void preprocesare()
{
    //generare reprezentare euler
    dfs(1,0);

    //calculare rmq
    lmax[1] = 0;
    for (int i = 2;i <= l_euler;++i)
        lmax[i] = lmax[i / 2] + 1;

    for (int i = 1;i <= l_euler;++i)
        rmq[0][i] = i;

    for (int i = 1;(1 << i) < l_euler;++i)
        for (int j = 1;j <= l_euler - (1 << i);++j)
        {
            int l = 1 << (i - 1);
            rmq[i][j] = rmq[i - 1][j];
            if (nivel[rmq[i][j]] > nivel[rmq[i - 1][j + l]])
                rmq[i][j] = rmq[i - 1][j + l];
        }
}

int lca(int a, int b)
{
    a = primul[a];
    b = primul[b];
    if (b < a)
        swap(a,b);
    int lung = b - a + 1;
    int l = lmax[lung];
    int poz1 = a, poz2 = a + lung - (1 << l);

    int sol = rmq[l][poz1];
    if (nivel[sol] > nivel[rmq[l][poz2]])
        sol = rmq[l][poz2];

    return euler[sol];
}

int main()
{
    int m;
    in >> n >> m;
    citire();
    preprocesare();
    for (int i = 1;i <= m;++i)
    {
        int x,y;
        in >> x >> y;
        out << lca(x, y) << '\n';
    }
    return 0;
}