Cod sursa(job #2409723)

Utilizator circeanubogdanCirceanu Bogdan circeanubogdan Data 19 aprilie 2019 12:53:39
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.85 kb
#include <fstream>
#include <vector>
#include <iostream>
#define DIM 100002

using namespace std;

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

int n, Q, x, y, eulerSize;
int father[DIM], pow2[4 * DIM];

pair<int, int> appeared[DIM];

pair<int, int> rmq[25][4 * DIM], euler[4 * DIM];

bool viz[DIM];

vector<int> arb[DIM];

void dfs(int nod, int level){
    viz[nod] = 1;
    euler[++eulerSize] = {level, nod};
    appeared[nod].first = eulerSize;
    
    for(auto nextNode : arb[nod]){
        if(viz[nextNode])
            continue;
        dfs(nextNode, level + 1);
        euler[++eulerSize] = {level, nod};
        appeared[nod].second = eulerSize;
    }
    
    if(appeared[nod].second == 0){
        euler[++eulerSize] = {level, nod};
        appeared[nod].second = eulerSize;
    }
}

int main(int argc, const char * argv[]) {
    
    in>>n>>Q;
    
    for(int i = 2; i <= n; ++ i){
        in>>x;
        arb[i].push_back(x);
        arb[x].push_back(i);
    }
    
    dfs(1, 1);
    
    pow2[1] = 0;
    for(int i = 2; i <= eulerSize; ++ i)
        pow2[i] = 1 + pow2[i / 2];
    
    for(int i = 1; i <= eulerSize; ++ i){
        rmq[0][i] = euler[i];
    }

    
    for(int i = 1; (1<<i) <= eulerSize; ++ i){
        for(int j = 1; j <= eulerSize; ++ j){
            if(j + (1<<(i - 1)) <= eulerSize)
                rmq[i][j] = min(rmq[i - 1][j], rmq[i - 1][j + (1<<(i - 1))]);
            else
                rmq[i][j] = rmq[i - 1][j];
            
        }
    }
    
    while(Q --){
        in>>x>>y;
        int left = min(appeared[x].first, appeared[y].first);
        int right = max(appeared[x].second, appeared[y].second);
        
        int pow = pow2[right - left + 1];
        
        pair<int, int> minim = min(rmq[pow][left], rmq[pow][right - (1<<pow) + 1]);
        
        out<<minim.second<<'\n';
        
    }
    
    
    
    return 0;
}