Pagini recente » Autentificare | Cod sursa (job #3357905) | Cod sursa (job #3357803) | Atasamentele paginii Profil vladparau100 | Cod sursa (job #3357875)
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
std::vector<int> euler;
std::vector<int> depth;
std::vector<int> euler_depth;
std::vector<std::vector<int>> tree;
std::vector<int> pos;
std::vector<int> rmq;
int block_size;
void dfs(int start) {
euler.push_back(start);
euler_depth.push_back(depth[start]);
pos[start] = euler.size() - 1;
for (const auto &x: tree[start]) {
depth[x] = depth[start] + 1;
dfs(x);
euler.push_back(start);
euler_depth.push_back(depth[start]);
}
}
int main() {
std::ifstream input("lca.in");
std::ofstream output("lca.out");
int n, m;
input >> n >> m;
tree.resize(n + 1);
depth.resize(n + 1, 0);
pos.resize(n + 1, -1);
for (int i = 2; i <= n; ++i) {
int x;
input >> x;
tree[x].push_back(i);
}
dfs(1);
int s = euler.size();
block_size = std::max(1, (int)std::sqrt(s));
int num_blocks = (s + block_size - 1) / block_size;
rmq.resize(num_blocks);
for (int i = 0; i < num_blocks; ++i) {
int start = i * block_size;
int end = std::min(start + block_size, s);
int min_pos = start;
for (int j = start; j < end; ++j) {
if (euler_depth[j] < euler_depth[min_pos]) {
min_pos = j;
}
}
rmq[i] = min_pos;
}
while (m--) {
int p, q;
input >> p >> q;
int left = pos[p];
int right = pos[q];
if (left > right) std::swap(left, right);
int min_pos = left;
int left_block = left / block_size;
int right_block = right / block_size;
if (left_block == right_block) {
for (int i = left; i <= right; ++i) {
if (euler_depth[i] < euler_depth[min_pos]) {
min_pos = i;
}
}
} else {
for (int i = left; i < (left_block + 1) * block_size; ++i) {
if (euler_depth[i] < euler_depth[min_pos]) {
min_pos = i;
}
}
for (int i = left_block + 1; i < right_block; ++i) {
int candidate = rmq[i];
if (euler_depth[candidate] < euler_depth[min_pos]) {
min_pos = candidate;
}
}
for (int i = right_block * block_size; i <= right; ++i) {
if (euler_depth[i] < euler_depth[min_pos]) {
min_pos = i;
}
}
}
output << euler[min_pos] << '\n';
}
return 0;
}