Pagini recente » Cod sursa (job #927587) | Cod sursa (job #2346088) | Cod sursa (job #2320877) | Cod sursa (job #1614127) | Cod sursa (job #2604861)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
struct node {
std::vector<int> children;
int parent;
int first_euler;
int level;
} nodes[100001];
int euler[200002];
int rmq[17][100001];
int log2[200002];
void dfs_euler(int node) {
static int euler_i;
euler[++euler_i] = node;
nodes[node].first_euler = euler_i;
for (const int child_id : nodes[node].children) {
auto& child = nodes[child_id];
if (child.first_euler == 0) {
child.level = nodes[node].level + 1;
dfs_euler(child_id);
euler[++euler_i] = node;
}
}
}
int lca(int n, int a, int b) {
int p = nodes[a].first_euler, q = nodes[b].first_euler;
if (p > q) {
std::swap(p, q);
}
int l = log2[q - p + 1];
int st = rmq[l][p + (1 << l) - 1];
int dr = rmq[l][q];
if (nodes[st].level < nodes[dr].level) {
return st;
} else {
return dr;
}
}
void compute_log2(int n) {
log2[1] = 0;
for (int i = 2; i <= 2 * n - 1; i++) {
log2[i] = log2[i / 2] + 1;
}
}
int main() {
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");
int n, m;
fin >> n >> m;
nodes[1].level = 0;
for (int i = 2; i <= n; i++) {
fin >> nodes[i].parent;
nodes[nodes[i].parent].children.push_back(i);
}
dfs_euler(1);
compute_log2(n);
// Pentru fiecare nod din parcurgerea Euler stim nivelul la care se afla.
// Calculam matricea RMQ pentru nivelul minim intr-un interval din parcurgerea Euler.
for (int j = 1; j <= 2 * n - 1; j++) {
rmq[0][j] = euler[j];
}
for (int i = 1; (1 << i) <= 2 * n - 1; i++) {
for (int j = 1; j <= 2 * n - 1; j++) {
int st = rmq[i - 1][j - (1 << (i - 1))];
int dr = rmq[i - 1][j];
if (nodes[st].level < nodes[dr].level) {
rmq[i][j] = st;
} else {
rmq[i][j] = dr;
}
}
}
for (int i = 0; i < m; i++) {
int a, b;
fin >> a >> b;
fout << lca(n, a, b) << '\n';
}
return 0;
}