Cod sursa(job #1833765)

Utilizator rares96cheseliRares Cheseli rares96cheseli Data 23 decembrie 2016 05:47:47
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.01 kb
#include <bits/stdc++.h>

#define NMAX 100005
#define LOG_NMAX 17

using namespace std;

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

vector < int > graph[NMAX], euler;
int level[NMAX], rmq[LOG_NMAX + 1][NMAX], first[NMAX], log_2[2 * NMAX], N, M;

void readInput() {
    f >> N >> M;
    for (int i = 2; i <= N; ++i) {
        int x;
        f >> x;
        graph[x].push_back(i);
    }
}

void dfs(int node, int currentLevel) {
    level[node] = currentLevel;
    euler.push_back(node);
    first[node] = euler.size();

    for (auto it : graph[node]) {
        dfs(it, currentLevel + 1);
        euler.push_back(node);
    }
}

void computeRmq() {
    rmq[0][1] = euler[0];
    for (int i = 2; i <= euler.size(); ++i) {
        log_2[i] = log_2[i / 2] + 1;
        rmq[0][i] = euler[i - 1];
    }

    for (int i = 1; (1 << i) <= euler.size(); ++i) {
        for (int j = 1; j <= euler.size() - (1 << i) + 1; ++j) {
            int x = rmq[i - 1][j];
            int y = rmq[i - 1][j + (1 << (i - 1))];

            /*
            *   Vreau nodul de nivel minim din parcurgerea Euler
            */
            if (level[x] < level[y]) {
                rmq[i][j] = x;
            } else {
                rmq[i][j] = y;
            }
        }
    }
}

int lca(int node1, int node2) {
    int left = first[node1];
    int right = first[node2];

    if (left > right) {
        swap(left, right);
    }

    int lg_2 = log_2[right - left + 1];
    int x = rmq[lg_2][left];
    int y = rmq[lg_2][right - (1 << lg_2) + 1];

    if (level[x] < level[y]) {
        return x;
    }

    return y;
}

void computeQueries() {
    for (int i = 1; i <= M; ++i) {
        int node1, node2;
        f >> node1 >> node2;
        g << lca(node1, node2) << '\n';
    }
}

int main() {
    clock_t tStart = clock();
    readInput();
    dfs(1, 0);
    computeRmq();
    computeQueries();
    printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
    return 0;
}