Cod sursa(job #1356743)

Utilizator retrogradLucian Bicsi retrograd Data 23 februarie 2015 16:04:53
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.96 kb
#include <fstream>
#include <vector>

using namespace std;
typedef int var;

ifstream fin("lca.in");
ofstream fout("lca.out");

#define MAXN 400001
#define MAXNLOGN 20

var n;
vector<var> G[MAXN];

vector<var> EULER(1), DEPTH(1);
var BEG[MAXN], D[MAXN], LOG[MAXN];
var RMQ[MAXNLOGN][MAXN],
    SOL[MAXNLOGN][MAXN];

void euler(var node) {
    BEG[node] = EULER.size();
    EULER.push_back(node);
    DEPTH.push_back(D[node]);

    for(vector<var>::iterator it = G[node].begin(); it != G[node].end(); ++it) {
        if(!BEG[*it]) {
            D[*it] = D[node] + 1;
            euler(*it);
            EULER.push_back(node);
            DEPTH.push_back(D[node]);
        }
    }
}


void build_log_table(var maxx) {
    for(var i=2; i<=maxx; i++) {
        LOG[i] = LOG[i/2] + 1;
    }
}

void build_lookup_table(var maxx) {
    for(var i=1; i<=maxx; i++) {
        RMQ[0][i] = DEPTH[i];
        SOL[0][i] = EULER[i];
    }
    for(var i=1; (1<<i) <= maxx; i++) {
        for(var j=1; j + (1<<i) - 1 <= maxx; j++) {
            if(RMQ[i-1][j] < RMQ[i-1][j + (1 << (i-1))]) {
                RMQ[i][j] = RMQ[i-1][j];
                SOL[i][j] = SOL[i-1][j];
            } else {
                RMQ[i][j] = RMQ[i-1][j + (1 << (i-1))];
                SOL[i][j] = SOL[i-1][j + (1 << (i-1))];
            }
        }
    }
}

var lca(var a, var b) {
    a = BEG[a];
    b = BEG[b];

    if(a > b) swap(a, b);

    var len = LOG[b-a+1];

    if(RMQ[len][a] < RMQ[len][b-(1<<len)+1]) {
        return SOL[len][a];
    } else {
        return SOL[len][b-(1<<len)+1];
    }

}


int main() {
    var m, a, b;
    fin>>n>>m;
    for(var i=2; i<=n; i++) {
        fin>>b;
        G[i].push_back(b);
        G[b].push_back(i);
    }

    euler(1);
    build_log_table(EULER.size());
    build_lookup_table(EULER.size() - 1);

    while(m--) {
        fin>>a>>b;
        fout<<lca(a, b)<<'\n';
    }


    return 0;
}