Cod sursa(job #2080432)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 2 decembrie 2017 22:46:57
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.8 kb
#include <bits/stdc++.h>
using namespace std;

constexpr int DIM = 400005;

vector< int > sons[DIM];
int rmq[21][DIM], counter, first_app[DIM], level[DIM];
int pow2[DIM];

void dfs(int node) {
    rmq[0][counter++] = node;
    first_app[node] = counter - 1;
    for (auto&& it : sons[node]) {
        level[it] = level[node] + 1;
        dfs(it);

        rmq[0][counter++] = node;
    }
}

void compute_rmq() {
    for (int i = 1; (1 << i) <= counter; ++i) {
        for (int j = 0; j < counter; ++j) {
            rmq[i][j] = rmq[i - 1][j];

            if (j + (1 << (i-1)) < counter
                && level[rmq[i - 1][j + (1 << (i-1))]] < level[rmq[i - 1][j]])
                rmq[i][j] = rmq[i - 1][j + (1 << (i-1))];
        }
    }
}

void precompute_powers_of_2() {
    pow2[1] = 0;
    for (int i = 2; i <= counter; ++i)
        pow2[i] = pow2[i / 2] + 1;
}

int lca(int first, int second) {
    first = first_app[first];
    second = first_app[second];

    if (first > second)
        swap(first, second);

    int pow = pow2[second - first + 1];

    if (level[ rmq[pow][first] ] < level[ rmq[pow][second - (1 << pow) + 1] ])
        return rmq[pow][first];
    else
        return rmq[pow][second - (1 << pow) + 1];
}

void solve() {
    int node_count, query_count;
    cin >> node_count >> query_count;

    for (int i = 2; i <= node_count; ++i) {
        int p;
        cin >> p;
        sons[p].push_back(i);
    }

    counter = 0;
    dfs(1);
    precompute_powers_of_2();
    compute_rmq();

    while (query_count--) {
        int first, second;
        cin >> first >> second;
        cout << lca(first, second) << '\n';
    }
}

int main() {
    assert(freopen("lca.in", "r", stdin));
    assert(freopen("lca.out", "w", stdout));
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    solve();

    return 0;
}