Cod sursa(job #2466396)

Utilizator aurelionutAurel Popa aurelionut Data 2 octombrie 2019 01:33:05
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.67 kb
#include <vector>
#include <fstream>
#include <algorithm>

using namespace std;

const int NMAX = 100005;
vector <int> graph[NMAX];
int nodes, queries;
int h[NMAX], euler[2 * NMAX], lgeuler, poseuler[2 * NMAX];
int lg[2 * NMAX], rmq[20][2 * NMAX];

void dfs(int node, int father)
{
    h[node] = h[father] + 1;
    euler[++lgeuler] = node;
    poseuler[node] = lgeuler;
    for (auto &x : graph[node])
    {
        dfs(x, node);
        euler[++lgeuler] = node;
    }
}

void BuildRMQ()
{
    for (int i = 2;i <= lgeuler;++i)
        lg[i] = lg[i >> 1] + 1;
    for (int i = 1;i <= lgeuler;++i)
        rmq[0][i] = i;
    for (int p = 1;(1 << p) <= lgeuler;++p)
        for (int i = 1;i + (1 << p) - 1 <= lgeuler;++i)
        {
            int a = rmq[p - 1][i];
            int b = rmq[p - 1][i + (1 << (p - 1))];
            if (h[euler[a]] < h[euler[b]])
                rmq[p][i] = a;
            else
                rmq[p][i] = b;
        }
}

int QueryRMQ(int a, int b)
{
    a = poseuler[a];
    b = poseuler[b];
    if (a > b)
        swap(a, b);
    int p = lg[b - a + 1];
    a = euler[rmq[p][a]];
    b = euler[rmq[p][b - (1 << p) + 1]];
    if (h[a] < h[b])
        return a;
    else
        return b;
}

int main()
{
    ifstream fin("lca.in");
    ofstream fout("lca.out");
    fin >> nodes >> queries;
    for (int i = 2;i <= nodes;++i)
    {
        int x;
        fin >> x;
        graph[x].push_back(i);
    }
    dfs(1, 0);
    BuildRMQ();
    while (queries-- > 0)
    {
        int a, b;
        fin >> a >> b;
        fout << QueryRMQ(a, b) << "\n";
    }
    fin.close();
    fout.close();
    return 0;
}