Cod sursa(job #1397336)

Utilizator bullseYeIacob Sergiu bullseYe Data 23 martie 2015 13:47:24
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.14 kb
#include <cstdio>
#include <vector>
#define NMAX 100010
using namespace std;
FILE*fin=fopen ("lca.in", "r");
FILE*fout=fopen ("lca.out", "w");

int n, m;
int A[4*NMAX], lga, log2lga;
int Euler[4*NMAX];
int M[4*NMAX][20];
int first[NMAX];
vector <int> L[NMAX];

void citire();
void DFS (int, int);
void precalculare();
int query(int, int);
void rez();
void afisare();

int main()
{
    int i, x;
    //citesc fii
    fscanf(fin, "%d %d", &n, &m);
    for (i=1; i<n; ++i)
    {
        fscanf(fin, "%d", &x);
        L[x].push_back(i+1);
    }
    DFS(1, 0);
    precalculare();
    rez();
    return 0;
}

void DFS (int nod, int nvl)
{
    int i;
    A[++lga]=nvl;//parcurgere euler, doar ca retin nivelurile in loc de noduri
    Euler[lga]=nod;
    if (!first[nod])
        first[nod]=lga;
    for (i=0; i<L[nod].size(); ++i)
    {
        DFS (L[nod][i], nvl+1);
        A[++lga]=nvl;
        Euler[lga]=nod;
    }
    return;
}

//M[i][j]=pozitia elementului minim in vectorul A din subsecventa care incepe la i si are lungimea 2^j
void precalculare()
{
    int i, j;
    for (log2lga=0, j=1; j<lga; j*=2, ++log2lga);
    //if ((1<<log2lga)-lga) --log2lga;

    for (i=1; i<=lga; ++i)
        M[i][0]=i;
    for (j=1; j<=log2lga; ++j)
        for (i=1; i+(1<<j)-1<=lga; ++i)
            if (A[M[i][j-1]]<A[M[i+(1<<(j-1))][j-1]])
                M[i][j]=M[i][j-1];
                else
                M[i][j]=M[i+(1<<(j-1))][j-1];
    return;
}

int query (int st, int dr)
{
    int lg, log2lg, ct;
    lg=dr-st+1;
    for (log2lg=0, ct=1; ct<lg; ct*=2, ++log2lg);
    if ((1<<log2lg)-lg) --log2lg;
    if (A[M[st][log2lg]] < A[M[dr-(1<<log2lg)+1][log2lg]])
        return M[st][log2lg];
        else
        return M[dr-(1<<log2lg)+1][log2lg];
}

void rez()
{
    int i, a, b;
    for (i=1; i<=m; ++i)
    {
        fscanf(fin, "%d %d", &a, &b);
        if (first[a]<first[b])
            fprintf(fout, "%d\n", Euler[query (first[a], first[b])]);
            else
            fprintf(fout, "%d\n", Euler[query (first[b], first[a])]);
    }
    fclose(fin);
    fclose(fout);
    return;
}