Cod sursa(job #2353094)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 23 februarie 2019 21:07:09
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.86 kb
#include <bits/stdc++.h>

#define MAXLOG   20
#define MAXN 100005

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

int N, M, Parent[MAXN];
std::vector <int> Sons[MAXN];

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

int EulerSize, Euler[4*MAXN], LVL[MAXN], Depth[MAXN],
    Euidx[MAXN];
void Liniarizare(int Vertex = 1) {
    LVL[Vertex] = LVL[Parent[Vertex]] + 1;
    Euler[++EulerSize] = Vertex;
    Euidx[Vertex] = EulerSize;
    Depth[EulerSize] = LVL[Vertex];

    for (auto Son:Sons[Vertex])
        if (!LVL[Son]) {
            Liniarizare(Son);
            Euler[++EulerSize] = Vertex;
            Depth[EulerSize] = LVL[Vertex];
        }
}

int RMQ[20][MAXN];
void BuildRMQ() {
    for (int i=1; i<=EulerSize; ++i)
        RMQ[0][i] = i;

    for (int lg=1, i; (1<<lg) <= EulerSize; ++lg)
        for (i=1; i + (1<<lg)-1 <= EulerSize; ++i) {
            if (Depth[RMQ[lg-1][i]] < Depth[RMQ[lg-1][i + (1<<(lg-1))]])
                RMQ[lg][i] = RMQ[lg-1][i];
            else
                RMQ[lg][i] = RMQ[lg-1][i + (1<<(lg-1))];
        }
}

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

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

void Citire() {
    In >> N >> M;
    for (int i=2, P; i<=N; ++i)
        In >> P, AddEdge(P, i);
}

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

    int X, Y;
    while (M--)
        In >> X >> Y,
        Out << LCA(X, Y) << '\n';
}

int main()
{
    Citire();
    Precompute();
    Rezolvare();

    return 0;
}