Cod sursa(job #3148905)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 5 septembrie 2023 02:30:52
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.83 kb
#include <fstream>
#include <vector>

using namespace std;

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

static constexpr int NMAX = (int)(1e5 + 1), LOGMAX = 20;
static const int ROOT = 1;

int Log[NMAX];

int N;
vector<int> G[NMAX];

int level[NMAX];
int t[LOGMAX][NMAX];

static inline int read()
{
    int q = 0;

    f.tie(nullptr);
    f >> N >> q;

    for (int i = 2; i <= N; ++i)
        f >> t[0][i], G[t[0][i]].push_back(i);

    return q;
}

static inline void go(const int &node = ROOT, const int &level_node = 0)
{
    level[node] = level_node;

    for (auto it : G[node])
        go(it, (level_node + 1));

    return;
}

static inline void precalculation()
{
    Log[1] = 0;
    for (int i = 2; i <= N; ++i)
        Log[i] = 1 + Log[(i >> 1)];

    for (int i = 1; i <= Log[N]; ++i)
        for (int j = 1; j <= N; ++j)
            t[i][j] = t[i - 1][t[i - 1][j]];

    return;
}

static inline void my_swap(int &a, int &b)
{
    a = (a ^ b), b = (a ^ b), a = (a ^ b);

    return;
}

static inline int get_lca(int &x, int &y)
{
    if (x == y)
        return x;

    if (t[0][x] == y)
        return y;
    if (t[0][y] == x)
        return x;

    if (level[y] < level[x])
        my_swap(x, y);

    int diff = level[y] - level[x];

    if (diff > 0)
        for (int i = Log[diff]; i >= 0; --i)
            if (diff & (1 << i))
                y = t[i][y];

    if (x == y)
        return x;

    int curr_level = level[x];
    for (int i = Log[curr_level]; i >= 0 && x && y; --i)
        if (t[i][x] && t[i][y] && t[i][x] != t[i][y])
            x = t[i][x], y = t[i][y];

    return t[0][x];
}

static inline void test_case()
{
    int x = 0, y = 0;
    f >> x >> y;

    g << get_lca(x, y) << '\n';

    return;
}

int main()
{
    int q = read();

    go();

    precalculation();

    for (int i = 1; i <= q; ++i)
        test_case();

    return 0;
}