Pagini recente » Cod sursa (job #2098857) | Cod sursa (job #278562) | Cod sursa (job #94391) | Cod sursa (job #2781952) | Cod sursa (job #2544684)
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int NMAX = 100505;
const int LMAX = (1 << 18);
const int SQRT_LMAX = (1 << 9);
int N, M;
vector<int> G[NMAX];
int euler[LMAX], firstEuler[NMAX], depth[NMAX], eulerIdx;
int sqrtLowest[SQRT_LMAX], sqrtEuler;
bool visited[NMAX];
void read() {
scanf("%d%d", &N, &M);
int x;
for (int node = 2; node <= N; node++) {
scanf("%d", &x);
G[x].push_back(node);
G[node].push_back(x);
}
}
void dfs(int node) {
visited[node] = true;
euler[++eulerIdx] = node;
firstEuler[node] = eulerIdx;
for (auto neighbour : G[node]) {
if (!visited[neighbour]) {
depth[neighbour] = depth[node] + 1;
dfs(neighbour);
euler[++eulerIdx] = node;
}
}
}
inline int lowerDepth(int node1, int node2) {
return depth[node1] < depth[node2] ? node1 : node2;
}
void precomputeSqrtLowest() {
sqrtEuler = (int) sqrt(eulerIdx * 1.0) + 1;
for (int posEuler = 1; posEuler <= eulerIdx; posEuler++) {
int bucket = posEuler / sqrtEuler;
sqrtLowest[bucket] = !sqrtLowest[bucket]
? euler[posEuler] : lowerDepth(sqrtLowest[bucket], euler[posEuler]);
}
}
int findNodeLowestDepth(int from, int to) {
if (from > to) {
swap(from, to);
}
int bucketFrom = from / sqrtEuler;
int bucketTo = to / sqrtEuler;
int nodeLowestDepth = euler[from];
if (bucketFrom == bucketTo) {
for (int posEuler = from + 1; posEuler <= to; posEuler++) {
nodeLowestDepth = lowerDepth(nodeLowestDepth, euler[posEuler]);
}
} else {
for (int posEuler = from, end = (bucketFrom + 1) * sqrtEuler; posEuler <= end; posEuler++) {
nodeLowestDepth = lowerDepth(nodeLowestDepth, euler[posEuler]);
}
for (int bucketIdx = bucketFrom + 1; bucketIdx < bucketTo; bucketIdx++) {
nodeLowestDepth = lowerDepth(nodeLowestDepth, sqrtLowest[bucketIdx]);
}
for (int posEuler = bucketTo * sqrtEuler; posEuler <= to; posEuler++) {
nodeLowestDepth = lowerDepth(nodeLowestDepth, euler[posEuler]);
}
}
return nodeLowestDepth;
}
void solve() {
dfs(1);
precomputeSqrtLowest();
int x, y;
for (int queryIdx = 0; queryIdx < M; queryIdx++) {
scanf("%d%d", &x, &y);
printf("%d\n", findNodeLowestDepth(firstEuler[x], firstEuler[y]));
}
}
int main() {
freopen("lca.in", "r", stdin);
freopen("lca.out", "w", stdout);
read();
solve();
return 0;
}