Pagini recente » Cod sursa (job #380118) | Cod sursa (job #1233793) | Cod sursa (job #2536672) | Cod sursa (job #2399473) | Cod sursa (job #2284800)
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <assert.h>
#include <queue>
#include <chrono>
#include <memory>
#include <cstring>
using LL = long long;
using ULL = int long long;
const std::string _problemName = "lca";
// #define USE_FILES
#ifdef USE_FILES
namespace std {
std::ifstream fin(_problemName + ".in");
std::ofstream fout(_problemName + ".out");
}
#define cin fin
#define cout fout
#endif
int n, m;
std::vector< std::vector<int> > ancestors;
std::vector<int> depths;
int computeLevel(int node) {
// TODO: might throw stack overflow?
if (depths[node] == -1) {
depths[node] = computeLevel(ancestors[0][node]) + 1;
}
return depths[node];
}
void computeDepths() {
depths.resize(n);
std::fill(depths.begin(), depths.end(), -1);
depths[0] = 1;
for (int node = 1; node < n; ++node) {
depths[node] = computeLevel(node);
}
}
int getAncestor(int heightExp, int node) {
if (node == -1) {
return -1;
}
return ancestors[heightExp][node];
}
void buildAncestors() {
bool done = false;
for (int heightExp = 1; !done; ++heightExp) {
ancestors.push_back(std::vector<int>(n));
done = true;
for (int node = 0; node < n; ++node) {
int firstAncestor = getAncestor(heightExp - 1, node);
int secondAncestor = getAncestor(heightExp - 1, firstAncestor);
if (secondAncestor != -1) {
done = false;
}
ancestors[heightExp][node] = secondAncestor;
}
}
}
int getDepth(int node) {
if (node == -1) {
return 0;
}
return depths[node];
}
void raise(int& node, int levelsCount) {
for (int i = 0; (1 << i) <= levelsCount; ++i) {
if (levelsCount & (1 << i)) {
node = getAncestor(i, node);
}
}
}
int lca(int node1, int node2) {
// assure node1 is the lower one (depths[node1] >= depths[node2])
if (depths[node1] < depths[node2]) {
std::swap(node1, node2);
}
// raise node1 to the same depth as node2
int depthDif = depths[node1] - depths[node2];
raise(node1, depthDif);
// node1 and node2 are now on the same level
if (node1 == node2) {
return node1;
}
// raise them together and find the common ancestor
int e = 0;
while (getAncestor(e, node1) != getAncestor(e, node2)) {
++e;
}
for (e = e - 1; e >= 0; --e) {
if (getAncestor(e, node1) != getAncestor(e, node2)) {
node1 = getAncestor(e, node1);
node2 = getAncestor(e, node2);
}
}
// assert getAncestor(0, node1) != -1
// assert getAncestor(0, node1) == getAncestor(0, node2)
return getAncestor(0, node1);
}
int main() {
std::cin >> n >> m;
ancestors.push_back(std::vector<int>(n));
ancestors[0][0] = -1;
for (int i = 1; i < n; ++i) {
std::cin >> ancestors[0][i];
--ancestors[0][i];
}
computeDepths();
buildAncestors();
for (int queryIdx = 0; queryIdx < m; ++queryIdx) {
int node1, node2;
std::cin >> node1 >> node2;
--node1;
--node2;
std::cout << lca(node1, node2) + 1 << '\n';
}
return 0;
}