Cod sursa(job #3357875)

Utilizator TestLicenta123Test Test TestLicenta123 Data 13 iunie 2026 19:19:05
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.56 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>

std::vector<int> euler;
std::vector<int> depth;
std::vector<int> euler_depth;
std::vector<std::vector<int>> tree;
std::vector<int> pos;
std::vector<int> rmq;
int block_size;

void dfs(int start) {
    euler.push_back(start);
    euler_depth.push_back(depth[start]);
    pos[start] = euler.size() - 1;
    
    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, -1);

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

    dfs(1);

    int s = euler.size();
    block_size = std::max(1, (int)std::sqrt(s));
    int num_blocks = (s + block_size - 1) / block_size;
    rmq.resize(num_blocks);

    for (int i = 0; i < num_blocks; ++i) {
        int start = i * block_size;
        int end = std::min(start + block_size, s);
        int min_pos = start;
        for (int j = start; j < end; ++j) {
            if (euler_depth[j] < euler_depth[min_pos]) {
                min_pos = j;
            }
        }
        rmq[i] = min_pos;
    }

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

        int left = pos[p];
        int right = pos[q];
        if (left > right) std::swap(left, right);

        int min_pos = left;
        int left_block = left / block_size;
        int right_block = right / block_size;

        if (left_block == right_block) {
            for (int i = left; i <= right; ++i) {
                if (euler_depth[i] < euler_depth[min_pos]) {
                    min_pos = i;
                }
            }
        } else {
            for (int i = left; i < (left_block + 1) * block_size; ++i) {
                if (euler_depth[i] < euler_depth[min_pos]) {
                    min_pos = i;
                }
            }
            for (int i = left_block + 1; i < right_block; ++i) {
                int candidate = rmq[i];
                if (euler_depth[candidate] < euler_depth[min_pos]) {
                    min_pos = candidate;
                }
            }
            for (int i = right_block * block_size; i <= right; ++i) {
                if (euler_depth[i] < euler_depth[min_pos]) {
                    min_pos = i;
                }
            }
        }

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

    return 0;
}