Cod sursa(job #3122321)

Utilizator 100pCiornei Stefan 100p Data 18 aprilie 2023 16:34:22
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.87 kb
#include <bits/stdc++.h>

#pragma GCC optimize("O3")
#define MAX 100000
#define FILES freopen("lca.in","r",stdin);\
              freopen("lca.out","w",stdout);

using namespace std;

vector<int> v[MAX + 5];
int n, q, up[MAX + 5][17], Time, levels;

int nodeIn[MAX + 5], nodeOut[MAX + 5];

void readInt(int &x)
{
    char c;
    while(1)
    {
        c = getchar();
        if(c < '0' || c > '9')
            continue;
        x = c - '0';
        break;
    }

    while(1)
    {
        c = getchar();
        if(c == EOF)
            break;
        if(c < '0' || c > '9')
            break;
        if(c >= '0' && c <= '9')
            x = x * 10 + c - '0';
    }

}

void dfs(int x)
{
    nodeIn[x] = ++Time;

    for(int i = 1; i <= levels; ++i)
        up[x][i] = up[up[x][i - 1]][i - 1];

    for(auto i : v[x])
    {
        if(!nodeIn[i])
        {
            up[i][0] = x;
            dfs(i);
        }
    }
    nodeOut[x] = ++Time;
}

bool isAncestor(int a, int b)
{
    return nodeIn[b] >= nodeIn[a] && nodeOut[b] <= nodeOut[a];
}

int lca(int a,int b)
{
    if(isAncestor(a, b))
        return a;
    if(isAncestor(a, b))
        return b;
    int exp = levels;
    while(exp >= 0)
    {
        while(exp >= 0 && !up[a][exp])
            exp--;
        while(exp >= 0 && isAncestor(up[a][exp], b))
            exp--;
        if(exp >= 0)
            a = up[a][exp];
    }
    return up[a][0];
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    FILES
    readInt(n);
    readInt(q);
    for(int i = 2; i <= n; ++i)
    {
        int a;
        readInt(a);
        v[a].push_back(i);
    }
    levels = log2(n);
    dfs(1);
    for(int i = 1; i <= q; ++i)
    {
        int a, b;
        readInt(a), readInt(b);
        std::cout << lca(a, b) << '\n';
    }
}