Cod sursa(job #3237186)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 6 iulie 2024 11:19:22
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.84 kb
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

static constexpr int LogMAX = (17), nMAX = ((int)(1e5) + 1);
int Log[nMAX];

int n, q;
int t[LogMAX][nMAX], level[nMAX];

vector<int> G[nMAX];

namespace in_parser
{
    static constexpr int BSIZE = (1 << 16);

    static int pos = (BSIZE - 1);
    static char buff[BSIZE];

    static char get_char()
    {
        ++pos;

        if (pos == BSIZE)
        {
            pos = 0;

            int n = fread(buff, 1, BSIZE, stdin);
            if (n != BSIZE)
                for (int i = n; i < BSIZE; ++i)
                    buff[i] = 0;
        }

        return buff[pos];
    }

    int get_int()
    {
        int answer = 0;

        for (;;)
        {
            char ch = get_char();

            if ((ch >= '0') && (ch <= '9'))
            {
                answer = ((int)(ch - '0'));
                break;
            }
        }

        for (;;)
        {
            char ch = get_char();

            if ((ch >= '0') && (ch <= '9'))
                answer = (answer * 10 + (int)(ch - '0'));
            else
                break;
        }

        return answer;
    }
};

void read()
{
    ios_base ::sync_with_stdio(false);
    cin.tie(nullptr);

    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);

    n = in_parser ::get_int(), q = in_parser ::get_int();

    for (int i = 2; i <= n; ++i)
        t[0][i] = in_parser ::get_int(), G[t[0][i]].push_back(i);

    return;
}

void dfs(const int node = 1, const int from = 0)
{
    if (node == 1)
        level[node] = 0;
    else
        level[node] = (1 + level[from]);

    for (const int &adj : G[node])
        dfs(adj, node);

    return;
}

void pre_process()
{
    dfs();

    Log[1] = 0;
    for (int i = 2; i <= n; ++i)
        Log[i] = (1 + Log[(i >> 1)]);

    for (int l = 1; l <= Log[n]; ++l)
        for (int node = 1; node <= n; ++node)
            t[l][node] = t[(l - 1)][t[(l - 1)][node]];

    return;
}

void up(int &x, const int delta)
{
    for (int i = Log[delta]; i >= 0; --i)
        if (delta & (1 << i))
            x = t[i][x];

    return;
}

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[x] != level[y])
    {
        if (level[x] > level[y])
            up(x, (level[x] - level[y]));
        else
            up(y, (level[y] - level[x]));
    }

    ///
    if (x == y)
        return x;
    ///

    for (int i = 16; i >= 0; --i)
        if (t[i][x] != t[i][y])
            x = t[i][x], y = t[i][y];

    return t[0][x];
}

void solve()
{
    int x = 0, y = 0;
    for (int i = 1; i <= q; ++i)
    {
        x = in_parser ::get_int(), y = in_parser ::get_int();

        printf("%d\n", get_lca(x, y));
    }

    return;
}

int main()
{
    read();

    pre_process();

    solve();

    return 0;
}