Pagini recente » Cod sursa (job #582158) | Cod sursa (job #2074385) | Cod sursa (job #1134370) | Cod sursa (job #753601) | Cod sursa (job #3040157)
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
using Graph = vector<vector<int>>;
constexpr int INF = 2e9;
class LCA {
vector<int> euler, first, level;
vector<bool> visited;
vector<vector<int>> rmq;
int N, M;
inline void dfs(const Graph& G, int node, int lvl) {
visited[node] = true;
level[node] = lvl;
first[node] = euler.size();
euler.push_back(node);
for (const int adj : G[node])
if (!visited[adj]) {
dfs(G, adj, lvl + 1);
euler.push_back(node);
}
}
public:
LCA(const Graph& G, int root) noexcept {
N = G.size();
first.resize(N);
level.resize(N);
visited.resize(N, false);
euler.reserve(2 * N);
dfs(G, root, 0);
M = euler.size();
rmq.resize((int)log2(M) + 1);
for (int i = 0; i < M; ++i)
rmq[0].push_back(euler[i]);
for (int i = 1; i < rmq.size(); ++i)
for (int j = 0; j + (1 << i) - 1 < M; ++j) {
const int l = rmq[i - 1][j];
const int r = rmq[i - 1][j + (1 << (i - 1))];
rmq[i].push_back(level[l] < level[r] ? l : r);
}
}
inline int query(int node1, int node2) const {
int l = first[node1], r = first[node2];
if (l > r) swap(l, r);
const int lg_len = (int)log2(r - l + 1);
const int ans1 = rmq[lg_len][l], ans2 = rmq[lg_len][r - (1 << lg_len) + 1];
return level[ans1] < level[ans2] ? ans1 : ans2;
}
};
ifstream fin("lca.in");
ofstream fout("lca.out");
int main() {
int N, M, node1, node2;
fin >> N >> M;
Graph G(N);
for (int i = 1; i < N; ++i) {
fin >> node1;
G[node1 - 1].push_back(i);
}
LCA lca(G, 0);
for (int i = 0; i < M; ++i) {
fin >> node1 >> node2;
--node1, --node2;
fout << lca.query(node1, node2) + 1 << '\n';
}
return 0;
}