Pagini recente » Cod sursa (job #3231845) | Cod sursa (job #1938186) | Cod sursa (job #868008) | Cod sursa (job #8705) | Cod sursa (job #2458906)
#include <bits/stdc++.h>
//#define input std::cin
//#define output std::cout
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:
LCACalculator(std::vector <std::vector <int>> &graph) {
if (_log2[2] == 0) precompute();
this->graph = &graph;
depth.resize(2*graph.size(), 0);
first.resize(graph.size(), 0);
DFS();
buildRMQ();
}
~LCACalculator() {
depth.clear();
first.clear();
}
int query(int v, int w) {
v = first[v];
w = first[w];
if (w < v) std::swap(v, w);
int len = _log2[w-v + 1];
int x = RMQ[len][v], y = RMQ[len][w - (1<<len)+1];
if (depth[x] < depth[y]) return euler[x];
return euler[y];
}
private:
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);
} std::vector <std::vector <int>> *graph;
std::vector <int> depth;
std::vector <int> first;
std::vector <int> euler;
std::vector <int> RMQ[20];
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)
RMQ[i][j] = ((depth[RMQ[i-1][j]] < depth[RMQ[i-1][j + (1<<(i-1))]]) ? RMQ[i-1][j] : RMQ[i-1][j + (1<<(i-1))]);
}
};
int LCACalculator::_log2[MAXN] = {0};
#define num int
inline void addEdge(std::vector <std::vector <int>> &graph, int x, int y) {
graph[x].push_back(y);
graph[y].push_back(x);
}
int N;
std::vector <std::vector <int>> ADC;
LCACalculator *calc;
int main()
{
int N, Q;
input >> N >> Q;
ADC.resize(N);
for (int i=1, x; i<N; ++i) {
input >> x;
addEdge(ADC, i, x-1);
} calc = new LCACalculator(ADC);
int x, y;
while (Q--) {
input >> x >> y;
output << calc->query(--x, --y)+1 << '\n';
}
return 0;
}