Cod sursa(job #2858320)

Utilizator MR0L3eXMaracine Constantin Razvan MR0L3eX Data 27 februarie 2022 12:56:50
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.04 kb
#include "bits/stdc++.h"
 
using namespace std;
 
using ld = long double;
using ll = long long;
using ull = unsigned long long;
 
#if defined(ONPC)
#include "bits/debug.h"
#endif
 
vector<vector<int>> adj;
vector<pair<int, int>> euler;
vector<int> depth, in;
int LOG = 1;
 
void dfs(int node = 0) {
    in[node] = (int)euler.size();
    euler.push_back({node, depth[node]});
    for (int u : adj[node]) {
        depth[u] = depth[node] + 1;
        dfs(u);
        euler.push_back({node, depth[node]});
    }
}

vector<vector<pair<int, int>>> st;

pair<int, int> get_min(const pair<int, int> &A, const pair<int, int> &B) {
    if (A.second < B.second)
        return A;
    return B;
}

void build_table() {
    int euler_sz = (int)euler.size();
    st.resize(euler_sz, vector<pair<int, int>>(LOG));
    for (int i = 0; i < euler_sz; ++i) {
        st[i][0] = euler[i];
    }
    for (int k = 1; k < LOG; ++k) {
        for (int i = 0; i + (1 << k) - 1 < euler_sz; ++i) {
            st[i][k] = get_min(st[i][k - 1], st[i + (1 << (k - 1))][k - 1]);
        }
    }
}

pair<int, int> qry(int L, int R) {
    int len = R - L + 1;

    // greatest pow of 2 that is smaller than len
    int k = 0;
    while (1 << (k + 1) <= len) ++k;

    return get_min(st[L][k], st[R - (1 << k) + 1][k]);
}

void init(int n) {
    while ((1 << LOG) <= n) ++LOG;
    adj.resize(n);
    in.resize(n);
    depth.resize(n);
}

void add_edge(int child) {
    int parent;
    cin >> parent;
    --parent;
    adj[parent].push_back(child);
}
   
int lca(int a, int b) {
    int L = in[a], R = in[b];
    if (L > R) swap(L, R);
    return qry(L, R).first;
}

void test_case() {
    int a, b;
    cin >> a >> b;
    --a, --b;
    cout << lca(a, b) + 1 << "\n";
}
 
int32_t main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);
    
    int n, Q;
    cin >> n >> Q;
    
    init(n);
    
    for (int i = 1; i < n; ++i) {
        add_edge(i);
    }
    
    dfs();
    build_table();
    
    while (Q--) {
        test_case();
    }
}