Cod sursa(job #969545)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 4 iulie 2013 16:39:02
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.2 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

int n, m, K;
vector <int> G[100010];
int euler[200010], height[200010], first[100010];
int lg[200010], rmq[18][200010];

inline void DFS(int nod, int nivel)
{
    K++;
    euler[K] = nod; /// bagam nod in reprezentarea euler a grafului
    height[K] = nivel; /// punem si nivelul la care se afla nod in graf
    first[nod] = K; /// punem prima aparitie a nodului nod in reprezentarea euler
    for (vector <int>::iterator it = G[nod].begin(); it!=G[nod].end(); it++)
    {
        DFS(*it, nivel+1);
        K++;
        euler[K] = nod; /// continuam reprezentarea euler a grafului
        height[K] = nivel; /// si nivelul
    }
}

inline void LG2()
{
    /// lg[i] = partea intreaga a lui log in baza 2 de i;
    int i;
    for (i=2; i<=K; i++)
    {
        lg[i] = lg[i>>1] + 1;
    }
}

inline void RMQ()
{
    ///rmq[i][j] = pozitia nodului de nivel minim din reprezentarea euler a grafului
    /// dintr-un interval care incepe la pozitia j si are lungime 2^i
    int i, j, lim;
    for (i=1; i<=K; i++)
        rmq[0][i] = i;
    for (i=1; (1<<i) <= K; i++)
    {
        lim = K - (1<<i) + 1;
        for (j=1; j <= lim; j++)
        {
            rmq[i][j] = rmq[i-1][j];
            if (height[rmq[i][j]] > height[rmq[i-1][j+(1 << (i-1))]])
                rmq[i][j] = rmq[i-1][j + (1 << (i-1))];
        }
    }
}

inline void compute()
{
    DFS(1, 0);
    LG2();
    RMQ();
}

inline int lca (int x, int y)
{
    int poz, dif, l;
    x = first[x]; /// extrag pozitiile din reprezentarea euler unde se afla nodurile
    y = first[y];
    if (x > y)
        swap(x, y);
    dif = y - x + 1;
    l = lg[dif];
    poz = rmq[l][x];
    if (height[poz] > height[rmq[l][x + dif - (1<<l)]])
        poz = rmq[l][x + dif - (1<<l)];
    return euler[poz];
}

int main()
{
    ifstream f ("lca.in");
    ofstream g ("lca.out");
    f>>n>>m;
    int i, x, y;
    for (i=1; i<n; i++)
    {
        f>>x;
        G[x].push_back(i+1);
    }
    compute();
    while (m--)
    {
        f>>x>>y;
        g<<lca(x, y)<<"\n";
    }
    f.close();
    g.close();
    return 0;
}