Cod sursa(job #1388642)

Utilizator japjappedulapPotra Vlad japjappedulap Data 15 martie 2015 16:51:22
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.48 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;

ifstream is ("lca.in");
ofstream os ("lca.out");

const int Nmax = 200001;
const int Lmax = 20;
const int INF = 0x3f3f3f3f;

int N, Q;

int Euler[Nmax<<1], Depth[Nmax<<1], Ind[Nmax], K, Log[Nmax<<1];
int RMQ[Lmax][Nmax];

vector <int> Tree[Nmax];
bool Vis[Nmax];


void Read();
inline void DFS(int node, int);
void RangeMinimumQuery();
inline int LCA(int A, int B);
inline int Distance(int A, int B);


int main()
{

    Read();
    DFS(1, 1);
    RangeMinimumQuery();
    for (int R, X, Y, Z, sol, node; Q; --Q)
    {
        is >> X >> Y;
        os << LCA(X, Y) << '\n';
        /*is >> R >> X >> Y;
        Z = LCA(X, Y);
        sol = Distance(R, Z) + Distance(X, Z) + Distance(Y, Z), node = Z;
        Z = LCA(X, R);
        if (sol > Distance(R, Z) + Distance(X, Z) + Distance(Y, Z))
            sol = Distance(R, Z) + Distance(X, Z) + Distance(Y, Z), node = Z;
        Z = LCA(R, Y);
        if (sol > Distance(R, Z) + Distance(X, Z) + Distance(Y, Z))
            sol = Distance(R, Z) + Distance(X, Z) + Distance(Y, Z), node = Z;
        cout << node << '\n';*/
    }
}

void Read()
{
    is >> N;
    is >> Q;
    for (int i = 2, x, y; i <= N; ++i)
    {
        is >> x;
        Tree[x].push_back(i);
        Tree[i].push_back(x);
    }
};

inline void DFS(int node, int lvl)
{
    Vis[node] = 1;
    Ind[node] = ++K;
    Euler[K] = node;
    Depth[K] = lvl;
    for (const int& next : Tree[node])
        if (Vis[next] == 0)
        {
            DFS(next, lvl+1);
            Euler[++K] = node;
            Depth[K] = lvl;
        }
}

void RangeMinimumQuery()
{
    for (int i = 1; i <= K; ++i)
        RMQ[0][i] = i;
    for (int i = 2; i <= K; ++i)
        Log[i] = Log[i >> 1] + 1;
    for (int i = 1, k; (1 << i) <= K; ++i)
        for (int j = 1; j + (1 << i) <= K+1; ++j)
            if (Depth[RMQ[i-1][j]] <= Depth[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))];
};

inline int LCA(int x, int y)
{
    int p1 = Ind[x], p2 = Ind[y];
    if (p1 > p2) swap(p1, p2);
    int k = Log[p2-p1];
    if (Depth[RMQ[k][p1]] <= Depth[RMQ[k][p2 - (1 << k) + 1]])
        return Euler[RMQ[k][p1]];
    return Euler[RMQ[k][p2 - (1 << k) + 1]];
};

inline int Distance(int A, int B)
{
    return Depth[B] + Depth[A] - 2 * Depth[LCA(A, B)];
};