Cod sursa(job #3309178)

Utilizator CatalinPangaleanuCatalin Pangaleanu CatalinPangaleanu Data 2 septembrie 2025 04:12:08
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.87 kb
#include <fstream>
#include <vector>
#include <algorithm>

void buildEulerRepresentation(int node, const std::vector<std::vector<int>> &adjacent, std::vector<int> &eulerRepresentation, std::vector<int> &level)
{
    eulerRepresentation.push_back(node);

    for (int neighbor: adjacent[node])
    {
        level[neighbor] = level[node] + 1;

        buildEulerRepresentation(neighbor, adjacent, eulerRepresentation, level);

        eulerRepresentation.push_back(node);
    }
}

int main()
{
    std::ifstream inFile("lca.in");

    int n, m;
    inFile >> n >> m;

    std::vector<std::vector<int>> adjacent(n + 1);

    for (int node = 2; node <= n; ++node)
    {
        int parent;
        inFile >> parent;

        adjacent[parent].push_back(node);
    }

    std::vector<int> eulerRepresentation, level(n + 1);
    eulerRepresentation.reserve(2 * n - 1);

    buildEulerRepresentation(1, adjacent, eulerRepresentation, level);

    std::vector<int> firstPosition(n + 1, -1);

    for (int i = 0; i < eulerRepresentation.size(); ++i)
    {
        if (firstPosition[eulerRepresentation[i]] == -1)
            firstPosition[eulerRepresentation[i]] = i;
    }

    int maxExponent = 18;

    std::vector<std::vector<int>> sparseTable(maxExponent);
    sparseTable[0] = eulerRepresentation;

    for (int i = 1; i < maxExponent; ++i)
    {
        if ((1 << i) > eulerRepresentation.size())
            break;

        sparseTable[i].resize(eulerRepresentation.size() - (1 << i) + 1);

        for (int j = 0; j + (1 << i) -1 < eulerRepresentation.size(); ++j)
        {
            if (level[sparseTable[i - 1][j]] < level[sparseTable[i - 1][j + (1 << (i - 1))]])
                sparseTable[i][j] = sparseTable[i - 1][j];
            else
                sparseTable[i][j] = sparseTable[i - 1][j + (1 << (i - 1))];
        }
    }

    std::vector<int> maxLength(eulerRepresentation.size() + 2);
    int currentMaxLength = 0;

    for (int i = 1; i < maxLength.size(); ++i)
    {
        if ((1 << (currentMaxLength + 1)) <= i)
            ++currentMaxLength;

        maxLength[i] = currentMaxLength;
    }

    std::ofstream outFile("lca.out");

    while (m--)
    {
        int node1, node2;
        inFile >> node1 >> node2;

        if (node1 == node2)
        {
            outFile << node1 << '\n';
            continue;
        }

        int first = std::min(firstPosition[node1], firstPosition[node2]), second = std::max(firstPosition[node1], firstPosition[node2]);
        int length = second - first + 1, answer;

        if (level[sparseTable[maxLength[length]][first]] < level[sparseTable[maxLength[length]][second - (1 << maxLength[length]) + 1]])
            answer = sparseTable[maxLength[length]][first];
        else
            answer = sparseTable[maxLength[length]][second - (1 << maxLength[length]) + 1];

        outFile << answer << '\n';
    }

    inFile.close();
    outFile.close();

    return 0;
}