Cod sursa(job #2874186)

Utilizator cyg_dawidDavid Ghiberdic cyg_dawid Data 19 martie 2022 13:11:20
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.42 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>

std::ifstream fin ("lca.in");
std::ofstream fout ("lca.out");

int const NMAX = 100000;
int const LGMAX = 18;

std::vector <int> children[NMAX + 5];
std::vector <int> euler;
int depth[NMAX + 5];

void dfs (int node, int parent) {
    depth[node] = depth[parent] + 1;

    int ssize = children[node].size();
    euler.push_back(node);
    for (int i = 0; i < ssize; i++) {
        if (children[node][i] == parent) continue;
        dfs (children[node][i], node);
        euler.push_back(node);
    }
}

int pozEuler[NMAX + 5];

void invEuler () {
    int ssize = euler.size();
    for (int i = 1; i < ssize; i++)
        pozEuler[euler[i]] = i;
}

int rmq[LGMAX + 5][2 * NMAX + 5];

void rmq_init () {
    int ssize = euler.size();
    for (int i = 1; i < ssize; i++)
        rmq[0][i] = i;
    for (int putere = 1; putere <= LGMAX; putere++) {
        for (int i = 1; i < ssize - (1 << putere) + 1; i++) {
            if (depth[euler[rmq[putere - 1][i]]] < depth[euler[rmq[putere - 1][i + (1 << (putere - 1))]]])
                rmq[putere][i] = rmq[putere - 1][i];
            else
                rmq[putere][i] = rmq[putere - 1][i + (1 << (putere - 1))];
        }
    }
}

int main()
{
    int n, m;
    fin >> n >> m;
    for (int i = 2; i <= n; i++) {
        int x;
        fin >> x;
        children[x].push_back(i);
    }
    euler.push_back(-1);
    dfs (1, 0);

    /*

    int ssize = euler.size();
    for (int i = 1; i < ssize; i++)
        fout << euler[i] << " ";
    fout <<"\n\n";
    for (int i = 1; i <= n; i++)
        fout << i << " " <<depth[i] << "\n";
    fout <<"\n\n";

    */

    invEuler ();
    rmq_init ();
    while (m--) {
        int x, y;
        fin >> x >> y;
        int candidatx = pozEuler[x];
        int candidaty = pozEuler[y];
        if (candidaty < candidatx)
            std::swap (candidatx, candidaty);
        if (candidatx == candidaty) {
            fout << euler[rmq[0][candidatx]] << "\n";
            continue;
        }
        int lg = (31 ^ __builtin_clz(candidaty - candidatx + 1));
        if (depth[euler[rmq[lg][candidatx]]] < depth[euler[rmq[lg][candidaty - (1 << lg) + 1]]])
            fout << euler[rmq[lg][candidatx]] << "\n";
        else
            fout << euler[rmq[lg][candidaty - (1 << lg) + 1]] << "\n";
    }
    return 0;
}