Cod sursa(job #1383949)

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

using namespace std;

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

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

void dfs(int nod, int niv)
{
    EULER[++K] = nod;
    LVL[K] = niv;
    First[nod] = K;

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

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

void rmq()
{
    logaritm[1] = 0;
    for (int i = 2; i <= K; ++i)
        logaritm[i] = logaritm[i / 2] + 1;
    for (int i = 1; i <= K; ++i)
        RMQ[0][i] = i;

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

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

int lca(int nod1, int nod2)
{
    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[l][start]] <= LVL[RMQ[l][finish - (1 << l) + 1]])
        sol = RMQ[l][start];
    else
        sol = RMQ[l][finish - (1 << l) + 1];

    return EULER[sol];
}

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

    dfs(1, 0);
    rmq();

    for (int i = 1, nod1, nod2; i <= M; ++i)
    {
        fin >> nod1 >> nod2;

        fout << lca(nod1, nod2) << '\n';
    }

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