Cod sursa(job #1661800)

Utilizator malina_floreaMalina Florea malina_florea Data 24 martie 2016 10:35:19
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.82 kb
#include <fstream>
#include <vector>
#define DMAX 100010 // de modificat DMAX
using namespace std;
FILE * fin = fopen ("lca.in", "r");
FILE * fout = fopen ("lca.out", "w");

struct element
{
    int vf, niv;
};

struct pozitii
{
    int min, max;
};


void citire();
void euler(element);
void gen();
int rez(int, int);
int query(int, int);
int putere2(int);

int n, m;
vector <int> lista[DMAX];

int ceu;
element eu[3*DMAX];

int pd[3*DMAX][20];

pozitii pozitie[DMAX];

int main()
{
    element start;
    int i, a, b;
    
    citire();
    
    start.vf=1, start.niv=0;
    euler(start);
    
    gen();
    
    for (i=1; i<=m; i++)
    {
        fscanf(fin, "%d %d", &a, &b);
        fprintf(fout, "%d\n", eu[rez(a, b)].vf);
    }
    
    fclose(fin);
    fclose(fout);
    return 0;
}

void citire()
{
    int x, tata;
    fscanf(fin, "%d %d", &n, &m);
    for (x=2; x<=n; x++)
    {
        fscanf(fin, "%d", &tata);
        lista[tata].push_back(x);
    }
}

void euler(element x)
{
    int i;
    element aux;
    
    eu[ceu++]=x;
    pozitie[x.vf].min=ceu-1;
    
    for (i=0; i<lista[x.vf].size(); i++)
    {
        aux.vf=lista[x.vf][i];
        aux.niv=x.niv+1;
        euler(aux);
        eu[ceu++]=x;
    }
    
    pozitie[x.vf].max=ceu-1;
}

void gen()
{
    int i, j, poz1, poz2;
    for (i=0; i<ceu; i++)
        pd[i][0]=i;
    
    for (j=1; (1<<j)<ceu; j++)
        for (i=0; i+(1<<j)-1<ceu; i++)
        {
            poz1=pd[i][j-1];
            poz2=pd[i+(1<<(j-1))][j-1];
            if (eu[poz1].niv<=eu[poz2].niv)
                pd[i][j]=poz1;
            else
                pd[i][j]=poz2;
        }
    
//    //afisare
//    for (i=0; i<ceu; i++)
//        fprintf(fout, "%d ", eu[i].vf);
//    fprintf(fout, "\n");
//    for (i=0; i<ceu; i++)
//        fprintf(fout, "%d ", eu[i].niv);
//    fprintf(fout, "\n");
//    
//    for (i=1; i<=n; i++)
//        fprintf(fout, "%d ", pozitie[i].min);
//    fprintf(fout, "\n");
//    for (i=1; i<=n; i++)
//        fprintf(fout, "%d ", pozitie[i].max);
//    fprintf(fout, "\n");
//    
//    for (i=0; i<ceu; i++)
//    {
//        for (j=0; (1<<j)<ceu; j++)
//            fprintf(fout, "%d ", pd[i][j]);
//        fprintf(fout, "\n");
//    }
//    // afisare
}

int rez(int nod1, int nod2)
{
    int min, max;
    
    if (pozitie[nod1].min<pozitie[nod2].min)
        min = pozitie[nod1].min;
    else
        min = pozitie[nod2].min;
    
    if (pozitie[nod1].max>pozitie[nod2].max)
        max = pozitie[nod1].min;
    else
        max = pozitie[nod2].max;
    
    return query(min, max);
}

int query(int a, int b)
{
    int poz1, poz2, k;
    k=putere2(b-a+1);
    
    poz1=pd[a][k];
    poz2=pd[b-(1<<k)+1][k];
    
    if (eu[poz1].niv<eu[poz2].niv)
        return poz1;
    else
        return poz2;
}

int putere2(int x)
{
    int k;
    for (k=0; (1<<k)<=x; k++);
    return k-1;
        
}