Cod sursa(job #1368921)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 2 martie 2015 20:39:08
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.66 kb
#include <cstdio>
#include <algorithm>
#include <vector>

#define Nmax 200105

#define adancime first
#define nod second

using namespace std;

vector<vector<int> > G;
vector<int> poz;
pair<int,int> DP[18][Nmax];

int N,Q,pzc;

void Read(){
    scanf("%d%d",&N,&Q);
    G.resize(N+1);
    poz.resize(N+1);
    int a;
    for(int i = 2; i <= N; ++i){
        scanf("%d",&a);
        G[a].push_back(i);
    }
}

void DFS(int k,int depth){
    DP[0][++pzc] = make_pair(depth,k);
    for(vector<int>::iterator it = G[k].begin(); it != G[k].end(); ++it)
    {
        DFS(*it,depth+1);
        DP[0][++pzc] = make_pair(depth,k);
    }
}

void RMQ()
{
    int limi = 0,IT = 1;
    while( (1<<(limi+1)) < pzc )
        ++limi;
    for(int i = 1; i <= limi; ++i)
    {
        for(int j = 1; j <= pzc; ++j)
            if(j + IT > pzc)
                DP[i][j] = DP[i-1][j];
            else
                DP[i][j] = min(DP[i-1][j],DP[i-1][j+IT]);
        IT *= 2;
    }
}

int Query(int a,int b)
{
    int x , y;
    x = poz[a];
    y = poz[b];
    if(x > y)
        swap(x,y);
    int len = y - x + 1,IT = 1,lin = 0;
    while( (IT<<1) <= len )
        IT<<=1,++lin;
    return min(DP[lin][x],DP[lin][y - IT + 1]).second;
}

void Solve()
{
    DFS(1,0);
    for(int i = 1; i <= pzc; ++i)
        if(!poz[DP[0][i].nod])
            poz[DP[0][i].nod] = i;
    RMQ();
    int a,b;
    for(int i = 1; i <= Q; ++i){
        scanf("%d%d",&a,&b);
        printf("%d\n",Query(a,b));
    }

}


int main()
{
    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);

    Read();
    Solve();

    return 0;
}