Cod sursa(job #681015)

Utilizator ion_calimanUAIC Ion Caliman ion_caliman Data 16 februarie 2012 12:58:31
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.56 kb
#include <fstream>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");

typedef struct NOD {
    int inf;
    struct NOD* next;
} NOD;

typedef struct {
    NOD* prim;
} LIST;


#define NMAX 100005
LIST T[NMAX];
int n, m;
int u, v;
int FIRST[NMAX], A[2*NMAX], B[2*NMAX];
int nr = 0;
int ADI[2*NMAX]; // Arbore de Intervale
int RMQ[2*NMAX][20];

void insereaza(LIST* L, int x)
{
    NOD* p=new(NOD);
    p->inf = x;
    p->next = L->prim;
    L->prim = p;
}

void DFS(LIST T[], int x, int p)
{
    nr++;
    FIRST[x] = nr;
    A[nr] = p;
    B[nr] = x;
    for (NOD* q=T[x].prim; q; q=q->next){
        DFS(T,q->inf,p+1);
        nr++;
        A[nr] = p;
        B[nr] = x;
    }
}

int minim(int l, int r)
{
    int p=l;
    for (int i=l+1; i<=r; i++)
        if (A[p]>A[i]) p = i;
    return B[p];
}

void creareADI(int p, int l, int r)
{
    if (l==r) {ADI[p] = l; return; }
    int t = (l+r)/2;
    creareADI(2*p+1,l,t);
    creareADI(2*p+2,t+1,r);
    if (A[ADI[2*p+1]] < A[ADI[2*p+2]])
        ADI[p] = ADI[2*p+1];
        else ADI[p] = ADI[2*p+2];
}

int minimADI(int p, int l, int r, int pi, int pf)
{
    if (l==pi && r==pf) return ADI[p];
    int t=(l+r)/2;
    if (pf<=t) return minimADI(2*p+1,l,t,pi,pf);
    if (pi>t) return minimADI(2*p+2,t+1,r,pi,pf);
    if (A[minimADI(2*p+1,l,t,pi,t)] < A[minimADI(2*p+2,t+1,r,t+1,pf)])
        return minimADI(2*p+1,l,t,pi,t);
        else return minimADI(2*p+2,t+1,r,t+1,pf);
}

void creareRMQ()
{
    int p,i,j,pmax=0;
    i=1;
    while (i*2<=nr) i*=2, pmax++;
    for (i=1; i<=nr; i++) RMQ[i][0] = i;
    for (p=1, i=1; p<=pmax; p++, i*=2){
        for (j=1; j+i<=nr; j++){
            if (A[RMQ[j][p-1]]<A[RMQ[j+i][p-1]]) RMQ[j][p] = RMQ[j][p-1]; else RMQ[j][p] = RMQ[j+i][p-1];
        }
    }
}

int RMQuery(int l, int r)
{
    int L=r-l+1, p=0, i;
    i = 1;
    while (i*2<=L) i*=2, p++;
    if (A[RMQ[l][p]]<A[RMQ[r-i+1][p]]) return B[RMQ[l][p]]; else return B[RMQ[r-i+1][p]];
}

int lca(int u, int v)
{
    int l, r;
    l = FIRST[u];
    r = FIRST[v];
    if (l>r) swap(l,r);
    return RMQuery(l,r);
    //return B[minimADI(0,1,nr,l,r)];
    //return minim(l,r);
}

int main()
{
    int x;
    f >> n >> m;
    for (int i=2; i<=n; i++){
        f >> x;
        insereaza (&T[x],i);
    }
    DFS(T,1,0);

    nr = FIRST[1];
    for (int i=2; i<=n; i++) if (nr<FIRST[i]) nr = FIRST[i];

    //creareADI(0,1,nr);
    creareRMQ();
    for (;m--;){
        f >> u >> v;
        g << lca(u,v) << '\n';
    }
    return 0;
}