Pagini recente » Cod sursa (job #510396) | Cod sursa (job #2740356) | Cod sursa (job #1720850) | Cod sursa (job #486731) | Cod sursa (job #2749930)
#include <bits/stdc++.h>
#define MAXN 100005
#define LOG2 20
class LCACalculator {
private:
static int _log2[MAXN];
static void precompute() {
for (int i=2; i<MAXN; ++i)
_log2[i] = _log2[i>>1] + 1;
}
public:
struct LCAData {
LCAData(int p=0) : parent(p) {}
int parent;
};
bool cmp(const LCAData &one, const LCAData &other) const {
return depth[one.parent] < depth[other.parent];
}
LCACalculator(std::vector <std::vector <int>> &graph) : graph(graph) {
if (_log2[2] == 0) precompute();
depth.resize(2*graph.size(), 0);
first.resize(graph.size(), 0);
DFS();
buildRMQ();
}
std::pair <int, LCAData> query(int v, int w) {
v = first[v];
w = first[w];
if (w < v) std::swap(v, w);
int len = _log2[w-v + 1];
auto x = RMQ[len][v], y = RMQ[len][w - (1<<len)+1];
if (cmp(x, y)) return {euler[x.parent], x};
return {euler[y.parent], x};
}
private:
std::vector <std::vector <int>> graph;
std::vector <int> depth;
std::vector <int> first;
std::vector <int> euler;
std::vector <LCAData> RMQ[20];
void DFS(int vertex = 0, int parent = 0, int lvl = 1) {
first[vertex] = euler.size();
depth[euler.size()] = lvl;
euler.push_back(vertex);
for (auto it:graph[vertex]) if (it != parent)
DFS(it, vertex, lvl+1),
depth[euler.size()] = lvl,
euler.push_back(vertex);
}
void buildRMQ() {
for (int i=0, size; (1<<i)<=euler.size(); ++i)
RMQ[i].resize(euler.size(), LCAData());
for (int i=0; i<euler.size(); ++i)
RMQ[0][i] = {i};
for (int i=1; (1<<i)<=euler.size(); ++i) {
for (int j=0; j+(1<<i)<=euler.size(); ++j) {
if (cmp(RMQ[i-1][j], RMQ[i-1][j + (1<<(i-1))]))
RMQ[i][j] = RMQ[i-1][j];
else RMQ[i][j] = RMQ[i-1][j + (1<<(i-1))];
}
}
}
};
int LCACalculator::_log2[MAXN] = {0};
std::ifstream input ("lca.in");
std::ofstream output("lca.out");
std::vector <std::vector <int>> graph;
int32_t main()
{
int N, M;
input >> N >> M;
graph.resize(N);
for (int i=1, u; i<N; ++i)
input >> u, graph[u-1].push_back(i), graph[i].push_back(u-1);
LCACalculator calc(graph);
for (int i=1, x, y; i<=M; ++i)
input >> x >> y, output << calc.query(x-1, y-1).first + 1 << '\n';
return 0;
}