Cod sursa(job #2340780)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 10 februarie 2019 23:35:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.39 kb
#include <bits/stdc++.h>

std::istream& operator >> (std::istream& stream, std::pair <int, int>& data) {
    return stream >> data.first >> data.second;
}

#define int_pair std::pair <int, int>

#define MAXN 200005
#define MAXLOG   20

int Log2[MAXN];
void Precompute() {
    Log2[1] = 0;
    for (int i=2; i<MAXN; ++i)
        Log2[i] = Log2[i>>1] + 1;
}

int N, K;
std::vector <int> ADC[MAXN];

inline void AddEdge(int X, int Y) {
    ADC[X].push_back(Y);
    ADC[Y].push_back(X);
}

int NEuler, Euler[MAXN], LVL[MAXN],
    Euleridx[MAXN], H[MAXN];
void Liniarizare(int Vertex = 1, int Height = 1, int Parent = 0) {
    Euler[++NEuler] = Vertex;
    LVL[NEuler] = Height;
    Euleridx[Vertex] = NEuler;
    H[Vertex] = Height;

    for (auto Edge:ADC[Vertex]) {
        if (Edge == Parent) continue;
        Liniarizare(Edge, Height+1, Vertex);
        Euler[++NEuler] = Vertex;
        LVL[NEuler] = Height;
    }
}

int RMQ[20][MAXN];
void BuildRMQ() {
    for (int i=1; i<=NEuler; ++i)
        RMQ[0][i] = i;
    for (int i=1, j; (1<<i)<NEuler; ++i)
        for (j=1; j <= NEuler-(1<<i)+1; ++j)
            if (LVL[RMQ[i-1][j]] < LVL[RMQ[i-1][j + (1<<(i-1))]])
                RMQ[i][j] = RMQ[i-1][j];
            else
                RMQ[i][j] = RMQ[i-1][j + (1<<(i-1))];
}

int LCA(int X, int Y) {
    X = Euleridx[X];
    Y = Euleridx[Y];
    if (X > Y) std::swap(X, Y);
    int Lg = Log2[Y-X+1];
    int A = RMQ[Lg][X], B = RMQ[Lg][Y - (1<<Lg)+1];
    if (LVL[A] < LVL[B])
        return Euler[A];
    return Euler[B];
}

std::ifstream In("lca.in");
std::ofstream Out("lca.out");

int_pair Terror[MAXN];
std::vector <int_pair> CT;

bool cmp(const int_pair& p0, const int_pair& p1) {
    return H[p0.first] > H[p1.first];
}

bool Seen[MAXN];
bool DFS(int Vertex) {
    Seen[Vertex] = 1;
    for (auto Edge:ADC[Vertex])
        if (!Seen[Edge] && H[Edge] > H[Vertex])
            DFS(Edge);
}

void Citire() {
    for (int i=1; i<=N; ++i)
        ADC[i].clear();

    In >> N >> K;
    for (int i=2, X, Y; i<=N; ++i)
        In >> X, AddEdge(X, i);
}

void Rezolvare() {
    Liniarizare();
    BuildRMQ();

    for (int i=1, X, Y; i<=K; ++i)
        In >> X >> Y, Out << LCA(X, Y) << '\n';
}

int main()
{
    Precompute();

    int T;
    T = 1;
    while (T--) {
        Citire();
        Rezolvare();
    }

    return 0;
}