Cod sursa(job #635029)

Utilizator marcelcodreaCodrea Marcel marcelcodrea Data 18 noiembrie 2011 11:03:26
Problema Lowest Common Ancestor Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.58 kb
#include<cstdio>
#define N 100005
int max(int a, int b) {
    if(a > b) return a;
    return b;
}
int powof2[25];
int M[18][4*N];
int arrH[4*N] = {0,};
int arrV[4*N] = {0,};
int posInEuler[N];
int LG[4*N];
struct Node {
    Node() {
        noOfSons = 0;
        sz = 100;
        sons = new Node*[100];
        for(int i = 0; i < 100; i++)
         sons[i] = 0;
    }

    int noOfSons;
    int sz;
    int v;
    Node** sons;
    void resize(int newsz) {
        int realnewsz = max(newsz, 2 * sz);
        Node** news = new Node*[realnewsz];
        for(int i = 0; i < noOfSons; i++)
         news[i] = sons[i];
        for(int i = noOfSons; i < realnewsz; i++)
         news[i] = 0;
        sons = news;
    }
};
struct LNode {
    int v;
    int level;
    LNode* next;
};
LNode* endOfList(LNode* h) {
    LNode* hea = h;
    while(hea -> next != 0) {
        hea = hea -> next;
    }
    return hea;
}
LNode* eulerTour(Node* r, int l) {
    if(r != 0) {
        LNode* b1 = new LNode();
        b1 -> v = r -> v;
        b1 -> level = l;
        b1 -> next = 0 ;
        LNode* b2,*ant = 0;
        for(int i = 0; i < r -> noOfSons; i++) {
            b2 = new LNode();
            b2 -> v = r -> v;
            b2 -> level = l;
            b2 -> next = 0;
            LNode* fl = eulerTour(r -> sons[i], l + 1);
            if (ant != 0) ant -> next = fl;
            if(i == 0) b1 -> next = fl;
            endOfList(fl) -> next = b2;
            ant = b2;
        }
        return b1;
    }
    return 0;
}
Node* convertToSon(int p[], int n) {
    Node** r = new Node*[n + 2];
    for(int i = 1; i <= n; i++) {
     r[i] = new Node();
     r[i] -> v = i;
    }
    for(int i = 2; i <= n; i++) {
        if(r[p[i]]->noOfSons >= r[p[i]]->sz)
         r[p[i]]->resize(r[p[i]]->noOfSons + 2);
        r[p[i]]->sons[r[p[i]]->noOfSons] = r[i];
        r[p[i]]->noOfSons++;
    }
    Node* aux = r[1];
    delete[] r;
    return aux;
}
int min(int a, int b) {
    if(a < b) return a;
    return b;
}
void init(int k) {
    for(int i = 0, p = 1; i < 19; i++, p*=2)
     powof2[i] = p;
    for(int i = 2; i <= k; i++)
     LG[i] = LG[i / 2] + 1;
}
void RMQ(LNode* lh, int p) {
    int nr = 0;
    LNode* aux = lh;
    while(aux != 0) {
        nr++;
        arrH[++arrH[0]] = aux -> level;
        arrV[++arrV[0]] = aux -> v;
        M[0][nr] = nr;
        if(posInEuler[aux->v] == 0)
         posInEuler[aux->v] = nr;
        aux = aux -> next;
    }
    init(nr);
    for(int i = 1; i <= 18; i++)  {
        int wh2go = nr - powof2[i] + 1;
        for(int j = 1; j <= wh2go; j++)
         if (arrH[M[i-1][j]] < arrH[M[i-1][j + powof2[i-1]]])
          M[i][j] = M[i-1][j];
         else
          M[i][j] = M[i-1][j + powof2[i-1]];
    }

    for(int i = 1; i <= p; i++) {
        int x, y;
        scanf("%d %d",&x,&y);
        int lf = posInEuler[x];
        int right = posInEuler[y];
        if(lf > right) {
            lf = posInEuler[y];
            right = posInEuler[x];
        }
        int how = right - lf + 1;
        int p = LG[how];
        if(arrH[M[p][lf]] < arrH[M[p][right-powof2[p] + 1]])
         printf("%d\n",arrV[M[p][lf]]);
        else
         printf("%d\n",arrV[M[p][right-powof2[p] + 1]]);
    }

}
int main() {
    int n, m;
    int p[N];
    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i = 2; i <= n; i++)
     scanf("%d", &p[i]);
    Node* r = convertToSon(p, n);
    LNode* z = eulerTour(r, 0);
    RMQ(z, m);
    return 0;
}