Cod sursa(job #3149444)

Utilizator PostoacaMateiMatei Postoaca PostoacaMatei Data 8 septembrie 2023 17:07:43
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.82 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

int n, q;
vector<int> gf[100001];

struct RmqItem {
    int nod, nvl;
};

int p_curent, p_start[200001];
RmqItem rmq[19][200001];
int max_bit[200001];

void dfs(int nod, int nvl = 1) {
    rmq[0][++p_curent] = { nod, nvl };
    p_start[nod] = p_curent;
    for (int fiu : gf[nod]) {
        dfs(fiu, nvl + 1);
        rmq[0][++p_curent] = { nod, nvl };
    }
}

void calculeaza_rmq() {
    for (int p = 1; p < 19; p++) // p < MAX_LOG
        for (int i = 1; i <= p_curent; i++) {
            RmqItem st = rmq[p - 1][i];
            if (i + (1 << (p - 1)) <= p_curent) {
                RmqItem dr = rmq[p - 1][i + (1 << (p - 1))];
                rmq[p][i] = st.nvl < dr.nvl ? st : dr;
            }
            else
                rmq[p][i] = st;
        }
}

void calculeaza_max_bit() {
    // calculeaza max_bit[i] cea mai mare putere a lui 2 <= i
    max_bit[1] = 0;
    for (int i = 2; i <= p_curent; i++)
        max_bit[i] = max_bit[i / 2] + 1;
}

int lca(int x, int y) {
    int pos_x = p_start[x];
    int pos_y = p_start[y];
    if (pos_x > pos_y)
        swap(pos_x, pos_y);
    int p = max_bit[pos_y - pos_x + 1];
    RmqItem st = rmq[p][pos_x];
    RmqItem dr = rmq[p][pos_y - (1 << p) + 1];
    if (st.nvl < dr.nvl)
        return st.nod;
    else
        return dr.nod;
}

int main() {
    fin >> n >> q;
    for (int i = 2; i <= n; i++) {
        int parinte;
        fin >> parinte;
        gf[parinte].push_back(i);
    }

    p_curent = 0;
    dfs(1);
    calculeaza_rmq();
    calculeaza_max_bit();

    for (int i = 1; i <= q; i++) {
        int x, y;
        fin >> x >> y;
        fout << lca(x, y) << "\n";
    }
    return 0;
}