Pagini recente » Cod sursa (job #1026427) | Cod sursa (job #2025737) | Cod sursa (job #1072391) | Cod sursa (job #1449081) | Cod sursa (job #1487074)
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
class tree {
private:
vector<vector<int>>& G;
int n, root;
vector<bool> mark;
vector<int> startPost, lvl, eulerPath, lg;
int currIdx;
vector<vector<int>> minInterval;
public:
tree(int _n, int _root, vector<vector<int>>& _G):
G(_G),
n(_n),
root(_root) { }
void prepareLca();
int findLca(int, int);
private:
void prepareEuler();
void dfs(int);
inline int minLevel(int, int);
void prepareRmq();
};
void tree:: prepareLca() {
mark.assign(n + 1, false);
startPost.resize(n + 1);
lvl.assign(n + 1, 0);
eulerPath.resize(2 * n + 1);
prepareEuler();
prepareRmq();
}
void tree:: prepareEuler() {
currIdx = 0;
dfs(root);
}
void tree:: dfs(int node) {
mark[node] = true;
startPost[node] = ++currIdx;
eulerPath[currIdx] = node;
for (auto x: G[node])
if (!mark[x]) {
lvl[x] = lvl[node] + 1;
dfs(x);
eulerPath[++currIdx] = node;
}
eulerPath[currIdx] = node;
}
inline int tree:: minLevel(int node1, int node2) {
return lvl[node1] < lvl[node2] ? node1 : node2;
}
void tree:: prepareRmq() {
lg.assign(currIdx + 1, 0);
for (int i = 2; i <= currIdx; i++)
lg[i] = lg[i >> 1] + 1;
int step;
for (step = 1; (1 << step) <= currIdx; step++);
minInterval.resize(step);
for (int i = 0; i < step; i++)
minInterval[i].resize(currIdx + 1);
for (int i = 1; i <= currIdx; i++)
minInterval[0][i] = eulerPath[i];
for (int j = 1; j < step; j++) {
for (int i = 1; i <= currIdx - (1 << j) + 1; i++) {
minInterval[j][i] = minLevel(
minInterval[j - 1][i],
minInterval[j - 1][i + (1 << (j - 1))]);
}
}
}
int tree:: findLca(int node1, int node2) {
if (startPost[node1] > startPost[node2]) {
swap(node1, node2);
}
int step = lg[startPost[node2] - startPost[node1] + 1];
return minLevel(
minInterval[step][startPost[node1]],
minInterval[step][startPost[node2] - (1 << step) + 1]);
}
int n, q;
vector<vector<int>> G;
tree* T;
void read() {
scanf("%d%d", &n, &q);
G.resize(n + 1);
int x;
for (int i = 2; i <= n; i++) {
scanf("%d", &x);
G[x].push_back(i);
G[i].push_back(x);
}
T = new tree(n, 1, G);
}
void solve() {
T -> prepareLca();
int x, y;
while (q--) {
scanf("%d%d", &x, &y);
printf("%d\n", T -> findLca(x, y));
}
}
int main() {
freopen("lca.in", "r", stdin);
freopen("lca.out", "w", stdout);
read();
solve();
return 0;
}