Cod sursa(job #1147767)

Utilizator cosmin.pascaruPascaru Cosmin cosmin.pascaru Data 20 martie 2014 09:34:32
Problema Lowest Common Ancestor Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 1.75 kb
#include <cstdio>
#include <vector>

#define pb push_back
#define NMAX 100005
#define EMAX 200005
#define LGMAX 20

using namespace std;

vector <int> a[NMAX];

int rmq[LGMAX][EMAX];

int first[NMAX];
int L[EMAX], lg[EMAX], v[EMAX];
int n, m, k;

void citire();
void df(int, int);
void make_rmq();
void answer();
int lca(int, int);

int main()
{
    citire();
    df(1,0);
    make_rmq();
    answer();

    return 0;
}
void citire()
{
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);

    int x;
    scanf("%d %d", &n, &m);

    for (int i = 2; i <= n; ++i)
    {
        scanf("%d", &x);
        a[x].pb(i);
    }
}

void df(int x, int niv)
{
    v[++k] = x;
    first[x] = k;
    L[k] = niv;

    for (vector<int>::iterator i = a[x].begin(); i != a[x].end(); ++i)
    {
        df(*i,niv+1);
        v[++k] = x;
        L[k]=niv;
    }
}

void make_rmq()
{
    int sh;

    for (int i = 2; i <= k; ++i) lg[i] = lg[i>>1]+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 < k - (1<<i); ++j)
        {
            sh = 1<<(i-1);

            rmq[i][j] = rmq[i-1][j];
            if ( L[rmq[i-1][j+sh]] < L[rmq[i][j]] )
                rmq[i][j] = rmq[i-1][j+sh];
        }
}

int lca(int x, int y)
{
    int a, b, sh, diff, sol, l;
    a = first[x];
    b = first[y];
    if (a>b) swap(a,b);

    diff = b - a + 1;
    l = lg[diff];
    sh = diff - (1 << l);
    sol = rmq[l][a];

    if (L[sol] > L[rmq[l][a+sh]])
        sol = rmq[l][a+sh];
    return v[sol];
}
void answer()
{
    int x,y;
    for (int i = 1; i <= m; ++i)
    {
        scanf("%d %d", &x, &y);
        printf("%d\n", lca(x,y));
    }
}