Cod sursa(job #3357914)

Utilizator TestLicenta123Test Test TestLicenta123 Data 13 iunie 2026 21:45:30
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.13 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <climits>

std::vector<int> euler(1, 0);
std::vector<int> depth;
std::vector<int> euler_depth(1, 0);
std::vector<std::vector<int>> tree;
std::vector<int> pos;
std::vector<int> rmq;

void dfs(int start) {
    euler.push_back(start);
    euler_depth.push_back(depth[start]);
    for (const auto &x: tree[start]) {
        depth[x] = depth[start] + 1;
        dfs(x);
        euler.push_back(start);
        euler_depth.push_back(depth[start]);
    }
}

int main() {
    std::ifstream input("lca.in");
    std::ofstream output("lca.out");

    int n, m;
    input >> n >> m;
    tree.resize(n + 1);
    depth.resize(n + 1, 0);
    pos.resize(n + 1, INT_MAX);

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

    dfs(1);

    size_t s = euler.size();
    for (size_t i = 0; i < s; ++i) {
        pos[euler[i]] = std::min<int>(pos[euler[i]], (int)i);
    }

    int root = 1;
    while (root * root <= s) root++;
    root--;

    int k = 0;
    while (k * root + 1 <= s) {
        int min = INT_MAX;
        int min_pos = 0;
        for (int i = k * root + 1; i <= std::min<int>((k + 1) * root, (int)s - 1); ++i) {
            if (euler_depth[i] < min) {
                min = euler_depth[i];
                min_pos = i;
            }
        }
        rmq.push_back(min_pos);
        k++;
    }

    while (m--) {
        int p, q;
        input >> p >> q;

        int left = std::min(pos[p], pos[q]);
        int right = std::max(pos[p], pos[q]);

        int min = INT_MAX;
        int min_pos = 0;
        for (int i = (left - 1) / root + 1; i < (right - 1) / root + 1; ++i) {
            if (euler_depth[rmq[i]] < min) {
                min = euler_depth[rmq[i]];
                min_pos = rmq[i];
            }
        }

        for (int i = std::max((left - 1) / root * root + 1, left); i <= std::min((right - 1) / root * root + root, right); ++i) {
            if (euler_depth[i] < min) {
                min = euler_depth[i];
                min_pos = i;
            }
        }

        output << euler[min_pos] << '\n';
    }

    return 0;
}