Cod sursa(job #2031138)

Utilizator LucaSeriSeritan Luca LucaSeri Data 2 octombrie 2017 19:25:58
Problema Lowest Common Ancestor Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 1.57 kb
#include <fstream>
#include <vector>
#include <iostream>

using namespace std;
const int Maxn = 1e5 + 1e3;
vector <int> gr[Maxn];
vector <int> euler;
int poz[Maxn];
int dp[Maxn<<1][20];
int logg[Maxn<<1];
int nivel[Maxn];
ifstream f("lca.in");
ofstream g("lca.out");

void dfs(int node, int lvl){
    nivel[node] = lvl;
    euler.push_back(node);
    poz[node] = euler.size()-1;
    for(auto x : gr[node]){
        dfs(x, lvl+1);
        euler.push_back(node);
    }
}

int query(int a, int b){
    if(a > b) swap(a, b);
    int l = logg[b-a];
    if(nivel[dp[a][l]] < nivel[dp[b-(1<<l)][l]])
        return dp[a][l];
    return dp[b-(1<<l)][l];
}
int main(){
    int n, m;
    f >> n >> m;
    for(int i = 2; i <= n; ++ i){
        int a;
        f >> a;
        gr[a].push_back(i);
    }

    for(int i = 2; i <= 2*n+100; ++ i){
        logg[i] = logg[i>>1]+1;
    }

    dfs(1, 1);
    for(int i = 0; i < euler.size()-1; ++ i){
        if(nivel[euler[i]] < nivel[euler[i+1]]){
            dp[i][0] = euler[i];
        }else dp[i][0] = euler[i+1];
    }
    for(int j = 1; j <= logg[n]; ++ j){
        for(int i = 0; i < euler.size(); ++ i){
            if(i + (1<<j) > euler.size()-1) break;
            if(nivel[dp[i][j-1]] < nivel[dp[i+(1<<j-1)][j-1]]){
                dp[i][j] = dp[i][j-1];
            }else dp[i][j] = dp[i+(1<<j-1)][j-1];
        }
    }

    for(int i = 0; i < m; ++ i){
        int a, b;
        f >> a >> b;
        if(a == b) g << a << '\n';
        else g << query(poz[a], poz[b]) << '\n';
    }
    return 0;
}