Cod sursa(job #3200817)

Utilizator not_anduAndu Scheusan not_andu Data 5 februarie 2024 20:13:15
Problema Lowest Common Ancestor Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.67 kb
#include <bits/stdc++.h>

using namespace std;

#define INFILE "lca.in"
#define OUTFILE "lca.out"

const int N_MAX = 1e5 + 5;
const int LOG_MAX = 10;

int n, queries;
int parent[LOG_MAX][N_MAX], depth[N_MAX];
vector<int> adj[N_MAX];

void generatingDepth(int node){
    for(auto to : adj[node]){
        depth[to] = depth[node] + 1;
        generatingDepth(to);
    }
}

void binaryLifting(){
    for(int i = 1; i < LOG_MAX; ++i){
        for(int j = 1; j <= n; ++j){
            parent[i][j] = parent[i - 1][parent[i - 1][j]];
        }
    }
}

int findAncestor(int node, int numberOfAncestor){

    if(numberOfAncestor >= (1 << LOG_MAX)) return 0;

    for(int i = 0; i < LOG_MAX; ++i){
        if(numberOfAncestor & (1 << i)) node = parent[i][node];
    }

    return node;

}

int lowestCommonAncestor(int node1, int node2){

    if(depth[node1] < depth[node2]) swap(node1, node2);

    node1 = findAncestor(node1, depth[node1] - depth[node2]);

    if(node1 == node2) return node1;

    for(int i = LOG_MAX - 1; i >= 0; --i){
        if(parent[i][node1] != parent[i][node2]) node1 = parent[i][node1], node2 = parent[i][node2];
    }

    return parent[0][node1];

}

void solve(){

    cin >> n >> queries;

    for(int i = 2; i <= n; ++i){
        cin >> parent[0][i];
        adj[parent[0][i]].push_back(i);
    }

    depth[1] = 0;
    generatingDepth(1);
    binaryLifting();

    for(int i = 0; i < queries; ++i){
        int node1, node2; cin >> node1 >> node2; cout << lowestCommonAncestor(node1, node2) << '\n';
    }

}

int main(){
    ios_base::sync_with_stdio(false);
    freopen(INFILE, "r", stdin);
    freopen(OUTFILE, "w", stdout);
    cin.tie(0), cout.tie(0);
    solve();
    return 0;
}