Cod sursa(job #2504981)

Utilizator GhSamuelGherasim Teodor-Samuel GhSamuel Data 5 decembrie 2019 21:56:48
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.65 kb
#include <bits/stdc++.h>
#define Nmax 100005
#define Lmax 20

using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");

int n, m;
int rmq[Nmax * Lmax][Lmax], lvl[Nmax * Lmax], first[Nmax], viz[Nmax];
vector <int> G[Nmax], euler;

void read()
{
    f >> n >> m;

    int x;
    for (int i = 2; i <= n; ++i) {
        f >> x;
        G[i].push_back(x);
        G[x].push_back(i);
    }
}

void dfs(int node, int level)
{
    viz[node] = 1;
    euler.push_back(node);

    int k = euler.size() - 1;
    lvl[node] = level;
    first[node] = k;
    for (int i = 0; i < G[node].size(); ++i)
        if (!viz[G[node][i]]) {
            dfs(G[node][i], level + 1);
            euler.push_back(node);
            lvl[euler.size() - 1] = level;
        }
}

void constructTree()
{
    for (int i = 1; i < euler.size(); ++i)
        rmq[i][0] = euler[i];

    for (int j = 1; (1 << j) < euler.size(); ++j)
        for (int i = 1; i + (1 << (j - 1)) - 1 < euler.size(); ++i) {
            int st = rmq[i][j - 1];
            int dr = rmq[i + (1 << (j - 1))][j - 1];
            if (lvl[st] < lvl[dr])
                rmq[i][j] = st;
            else
                rmq[i][j] = dr;
        }
}

int ask(int ls, int rs)
{
    if (ls > rs)
        swap(ls, rs);
    int k = floor(log2(rs - ls + 1));
    return min(rmq[ls][k], rmq[rs - (1 << k) + 1][k]);
}

void solve()
{
    constructTree();
    int x, y;
    for (int i = 0; i < m; ++i) {
        f >> x >> y;
        g << ask(first[x], first[y]) << "\n";
    }
}

int main()
{
    read();
    euler.push_back(-1);
    dfs(1, 0);
    solve();
    return 0;
}