Pagini recente » Cod sursa (job #846053) | Cod sursa (job #3003265) | Cod sursa (job #1673072) | Cod sursa (job #2904096) | Cod sursa (job #2749931)
#include <bits/stdc++.h>
std::ifstream input ("lca.in");
std::ofstream output("lca.out");
#define MAXN 2000005
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 { int v; };
LCACalculator(const 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();
}
bool cmp(const LCAData &x, const LCAData &y) const {
return depth[x.v] < depth[y.v];
}
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.v], x };
return { euler[y.v], y };
}
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(), { 0 });
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};
int main()
{
std::vector <std::vector <int>> graph;
int N, Q;
input >> N >> Q;
graph.resize(N);
for (int i=1, x; i<N; ++i) {
input >> x;
graph[i].push_back(x-1), graph[x-1].push_back(i);
}
auto calc = LCACalculator(graph);
int x, y;
while (Q--) {
input >> x >> y;
output << calc.query(x-1, y-1).first + 1 << '\n';
}
return 0;
}