Cod sursa(job #1162933)

Utilizator cbanu96Banu Cristian cbanu96 Data 1 aprilie 2014 02:29:39
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.83 kb
#include <cstdio>
#include <vector>

using namespace std;

#define FILEIN "lca.in"
#define FILEOUT "lca.out"
#define NMAX 100005
#define LGMAX 22

int LG       [NMAX << 1],
    EulerTour[NMAX << 1],
    EulerLvl [NMAX << 1],
    First    [NMAX << 1],
    RMQ[NMAX << 2][LGMAX],
    N, M, Pos = 0;

vector<int> A[NMAX];

void EulerTraversal(int x, int depth) {
    EulerTour[++Pos] = x;
    EulerLvl [Pos] = depth;
    First    [x] = Pos;

    for ( vector<int>::iterator it = A[x].begin(); it != A[x].end(); ++it ) {
        EulerTraversal(*it, depth + 1);

        EulerTour[++Pos] = x;
        EulerLvl [Pos] = depth;
    }
}

void BuildRMQ() {
    LG[1] = 0;
    for ( int i = 2; i <= Pos; i++ )
        LG[i] = LG[i/2] + 1;

    for ( int i = 1; i <= Pos; i++ ) {
        RMQ[i][0] = i;
    }

    for ( int j = 1; (1 << j) <= Pos; j++ ) {
        for ( int i = 1; i + (1 << (j-1)) <= Pos; i++ ) {
            RMQ[i][j] = RMQ[i][j-1];

            if (EulerLvl[RMQ[i + (1 << (j-1))][j-1]] < EulerLvl[RMQ[i][j]]) {
                RMQ[i][j] = RMQ[i + (1 << (j-1))][j-1];
            }
        }
    }
}

inline int LCA(int x, int y) {
    int xPos = First[x],
        yPos = First[y];

    if (xPos > yPos) {
        int tmp = xPos;
        xPos = yPos;
        yPos = tmp;
    }

    int L = LG[yPos - xPos + 1];

    int sol = RMQ[xPos][L];

    if (EulerLvl[RMQ[yPos - (1 << L) + 1][L]] < EulerLvl[RMQ[xPos][L]]) {
        sol = RMQ[yPos - (1 << L) + 1][L];
    }

    return EulerTour[sol];
}

int main() {
    freopen(FILEIN, "r", stdin);
    freopen(FILEOUT, "w", stdout);

    scanf("%d %d", &N, &M);
    for ( int i = 1, x; i < N; i++ ) {
        scanf("%d", &x);
        A[x].push_back(i+1);
    }

    EulerTraversal(1, 0);
    BuildRMQ();

    for ( int x, y; M; M-- ) {
        scanf("%d %d", &x, &y);
        printf("%d\n", LCA(x, y));
    }

    return 0;
}