Cod sursa(job #1119741)

Utilizator mircea.dobreanuMircea Dobreanu mircea.dobreanu Data 24 februarie 2014 19:49:04
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.79 kb
#include<fstream>
#include<vector>
using namespace std;
const int INF=(1<<30)-1;
const int MAXN=100005;
const int MAX_LOG=20;

int n,m,lge;
int H[MAXN],E[2*MAXN],L[2*MAXN],logaritm[MAXN];
int RMQ[MAXN][MAX_LOG];
vector<int> G[MAXN];
ifstream fin("lca.in");
ofstream fout("lca.out");



void dfs(int u, int nivel)
{
    H[u]=min(H[u], lge);
    E[++lge]=u;
    L[lge]=nivel;

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

        E[++lge]=u;
        L[lge]=nivel;
    }
}
void rmq_preprocess()
{
    /*CALCULEAZA POZITIA PE CARE O OCUPA NODUL CEL MAI
    APROPIAT DE RADACINA IN VECTORUL E
    DIN INTERVALUL [i,i+2^j-1]
    */
    int i,j;
    for (i=2; i<=lge; ++i)
        logaritm[i]=logaritm[i/2]+1;
    for (i=1; i<=lge; ++i)
        RMQ[i][0]=i;

    for (j=1; (1<<j)<=lge; ++j)
    {
        for (i=1; i+(1<<j)<=lge; ++i)
        {
            if (L[RMQ[i][j-1]]<L[RMQ[i+(1<<(j-1))][j-1]])
                RMQ[i][j]=RMQ[i][j-1];
            else
                RMQ[i][j]=RMQ[i+(1<<(j-1))][j-1];
        }
    }
}
int rmq_query(int i,int j)
{
    int k;
    k=logaritm[j-i];

    if (L[RMQ[i][k]] < L[RMQ[i+(1<<k)][k]])
        return RMQ[i][k];
    else
        return RMQ[i+(1<<k)][k];
}
int lca(int u, int v)
{
    int a=H[u], b=H[v], diff, sol;
    if (a>b)
        swap(a,b);
    diff=b-a+1;


    if (RMQ[a][logaritm[diff]] < RMQ[b-diff+1][logaritm[diff]])
        sol=RMQ[a][logaritm[diff]];
    else
        sol=RMQ[b-diff+1][logaritm[diff]];


    return E[sol];
}
int main()
{
    int i,x,y;
    fin>>n>>m;
    for (i=2; i<=n; ++i)
    {
        fin>>x;
        G[x].push_back(i);
    }

    for (i=1; i<=2*n; H[i]=INF, ++i);
    dfs(1,0);
    rmq_preprocess();

    for (i=1; i<=m; ++i)
    {
        fin>>x>>y;
        fout<<lca(x,y)<<'\n';
    }
    return 0;
}