Cod sursa(job #2452725)

Utilizator AlexandruGabrielAliciuc Alexandru AlexandruGabriel Data 1 septembrie 2019 00:04:16
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.61 kb
#include <bits/stdc++.h>
#define N 100005

using namespace std;

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

int n, m, k;
int level[N], first[N], a[4 * N], dp[32][4 * N], lg2[4 * N];
vector <int> G[N];

void DFS(int nod, int height)
{
    k++;
    level[nod] = height;
    first[nod] = k;
    a[k] = nod;
    for (auto next_nod : G[nod])
    {
        DFS(next_nod, height + 1);
        a[++k] = nod;
    }
}

inline int p2(int x)
{
    return (1 << x);
}

void RMQ()
{
    for (int i = 2; i <= k; i++)
        lg2[i] = lg2[i / 2] + 1;
    for (int i = 1; i <= k; i++)
        dp[0][i] = a[i];

    for (int i = 1; i <= lg2[k]; i++)
    {
        for (int j = 1; j <= k; j++)
        {
            if (j + p2(i) - 1 <= k)
            {
                if (level[dp[i - 1][j]] <= level[dp[i - 1][j + p2(i - 1)]])
                    dp[i][j] = dp[i - 1][j];
                else
                    dp[i][j] = dp[i - 1][j + p2(i - 1)];
            }
        }
    }
}

int LCA(int x, int y)
{
    int st = first[x], dr = first[y];
    if (st > dr)
        swap(st, dr);

    int pt = lg2[dr - st + 1];
    int ind = dr - p2(pt) + 1;

    if (level[dp[pt][st]] <= level[dp[pt][ind]])
        return dp[pt][st];
    else
        return dp[pt][ind];
}

int main()
{
    fin >> n >> m;
    for (int i = 2; i <= n; i++)
    {
        int TT;
        fin >> TT;
        G[TT].push_back(i);
    }
    DFS(1, 0);
    RMQ();

    for (int i = 1; i <= m; i++)
    {
        int x, y;
        fin >> x >> y;
        fout << LCA(x, y) << "\n";
    }
    return 0;
}