Cod sursa(job #1912056)

Utilizator misu007Pogonaru Mihai misu007 Data 7 martie 2017 22:50:08
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.91 kb
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>

#define NMAX 100001
#define LOGMAX 18
#define NE (unsigned)((1<<31) + 1)

using namespace std;

unsigned n, m, maxH = 0, impartire;
unsigned T[NMAX], H[NMAX];

unsigned lg[NMAX];
vector<vector<unsigned>> tatiLog;

unsigned Tsqrt[NMAX];
vector<unsigned> Copchi[NMAX];

unsigned lcaLG(unsigned i, unsigned j) {
    if (H[i] < H[j]) {
        swap(i, j);
    }

    for (unsigned k = lg[H[i]]; k > 0 && H[i] != H[j]; --k) {
        if (tatiLog[k][i] != NE && H[tatiLog[k][i]] >= H[j]) {
            i = tatiLog[k][i];
        }
    }

    //pt k = 0
    if (H[tatiLog[0][i]] >= H[j]) {
        i = tatiLog[0][i];
    }

    if (i == j) {
        return i + 1;
    }

    for (unsigned k = lg[H[i]]; k > 0 && T[i] != T[j]; --k) {
        if (tatiLog[k][i] != tatiLog[k][j]) {
            i = tatiLog[k][i];
            j = tatiLog[k][j];
        }
    }

    //pt k = 0
    if (tatiLog[0][i] != tatiLog[0][j]) {
        i = tatiLog[0][i];
        j = tatiLog[0][j];
    }

    return T[i] + 1;
}

void solveLG() {
    unsigned i, j;
//    for (unsigned j = 0; (unsigned)(1 << j) <= maxH; ++j) {
//        cout << j <<": ";
//        for (unsigned i = 0; i < n; ++i) {
//            cout<<tatiLog[j][i] << ", ";
//        }
//        cout<<endl;
//    }
    while (m--) {
        scanf("%d%d", &i, &j);
        printf("%d\n", lcaLG(i - 1, j - 1));
    }
}

void preprocessLG() {
    tatiLog.push_back(vector<unsigned>(n));
    tatiLog[0][0] = NE;
    for (unsigned i = 1; i < n; ++i) {
        tatiLog[0][i] = T[i];
    }

    for (unsigned j = 1; (unsigned)(1 << j) <= maxH; ++j) {
        tatiLog.push_back(vector<unsigned>(n, NE));
        for (unsigned i = 0; i < n; ++i) {
            if (tatiLog[j-1][i] != NE) { // echivalent cu H[i] - (1<<(j-1)) >= 0
                tatiLog[j][i] = tatiLog[j-1][tatiLog[j-1][i]];
            }
        }
    }

    lg[0] = 0;
    lg[1] = 0;
    for (unsigned i = 2; i <= maxH; ++i) {
        lg[i] = lg[i >> 1] + 1;
    }
}

unsigned lcaSQRT(unsigned i, unsigned j) {
    while (Tsqrt[i] != Tsqrt[j]) {
        if (H[i] > H[j]) {
            i = Tsqrt[i];
        } else {
            j = Tsqrt[j];
        }
    }
    while (i != j) {
        if (H[i] > H[j]) {
            i = T[i];
        } else {
            j = T[j];
        }
    }
    return i + 1;
}

void solveSQRT() {
    unsigned i, j;
    while (m--) {
        scanf("%d%d", &i, &j);
        printf("%d\n", lcaSQRT(i - 1, j - 1));
    }
}

void preprocessSQRT() {
    for (unsigned i = 0; i < n; ++i) {
        unsigned lev = H[i] / impartire;
        unsigned tatal = T[i];
        lev = lev < 1 ? lev : lev - 1;
        while (H[tatal] / impartire != lev) {
            tatal = T[tatal];
        }
        Tsqrt[i] = tatal;
    }
}

void dfsSQRT(unsigned nod, unsigned tatal) {
    if (!(H[nod] % impartire)) {
       tatal = T[nod];
    }

    Tsqrt[nod] = tatal;

    for (auto it : Copchi[nod]) {
        dfsSQRT(it, tatal);
    }
}

unsigned inaltime(unsigned nod) {
    if (nod == 0) {
        return 0;
    }

    if (!H[T[nod]]) {
        return inaltime(T[nod]) + 1;
    }

    return H[T[nod]] + 1;
}

void inaltime() {
    for (unsigned i = 0; i < n; ++i) {
        H[i] = inaltime(i);
        maxH = max(maxH, H[i]);
    }
    impartire = sqrt(maxH);
}

void read() {
    unsigned tatal;
    scanf("%d%d", &n, &m);
    T[0] = 0;
    H[0] = 0;
    for (unsigned i = 1; i < n; ++i) {
        scanf("%d", &tatal);
        --tatal;
        T[i] = tatal;
        //Copchi[tatal].push_back(i);
    }
}

int main()
{
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);
    read();
    inaltime();
    preprocessSQRT();
    //dfsSQRT(0, 0);
    solveSQRT();
    //preprocessLG();
    //solveLG();
    return 0;
}