Cod sursa(job #1383943)

Utilizator Ionut228Ionut Calofir Ionut228 Data 10 martie 2015 19:26:27
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.24 kb
#include <fstream>
#include <vector>

using namespace std;

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

int K, N, M;
int LVL[200002], EULER[200002], logaritm[200002], First[100001];
int RMQ[200002][20];
vector<int> V[100001];

void dfs(int nod, int nivel)
{
    EULER[++K] = nod; //nodul actual este adaugat in reprezentarea Euler a arborelui
    LVL[K] = nivel; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui
    First[nod] = K; //se retine prima aparitie a fiecarui nod in reprezentarea Euler

    for (vector<int>::iterator it = V[nod].begin(); it != V[nod].end(); ++it)
    {
        dfs(*it, nivel + 1);

        EULER[++K] = nod;
        LVL[K] = nivel;
    }
}

void rmq()
{
    //in RMQ[i][j] va fi nodul de nivel minim dintre pozitiile (j, j + 2 ^ (i - 1)) din reprezentarea Euler a arborelui
    logaritm[1] = 0;
    for (int i = 2; i <= K; ++i)
        logaritm[i] = logaritm[i >> 1] + 1;
    for (int i = 1; i <= K; ++i)
        RMQ[i][0] = i;

    for (int j = 1; (1 << j) <= K; ++j)
        for (int i = 1; i + (1 << (j - 1)) <= K; ++i)
        {
            int p  = 1 << (j - 1);

            if (LVL[RMQ[i][j - 1]] <= LVL[RMQ[i + p][j - 1]]) RMQ[i][j] = RMQ[i][j - 1];
            else                                              RMQ[i][j] = RMQ[i + p][j - 1];
        }
}

int lca(int nod1, int nod2)
{
    //LCA-ul nodurilor nod1 si nod2 va fi nodul cu nivel minim din secventa (First[nod1], First[nod2]) din reprezentarea Euler
    int sol;
    int start = First[nod1];
    int finish = First[nod2];

    if (start > finish) swap(start, finish);
    int dif = finish - start + 1;
    int l = logaritm[dif];

    if (LVL[RMQ[start][l]] <= LVL[RMQ[finish - (1 << l) + 1][l]]) sol = RMQ[start][l];
    else                                                          sol = RMQ[finish - (1 << l) + 1][l];

    return EULER[sol];
}

int main()
{
    fin >> N >> M;
    for (int i = 2, x; i <= N; ++i)
    {
        fin >> x;
        V[x].push_back(i);
    }

    dfs(1, 0);
    rmq();

    for (int i = 1; i <= M; ++i)
    {
        int a, b;
        fin >> a >> b;
        fout << lca(a, b) << '\n';
    }

    fin.close();
    fout.close();
    return 0;
}