Pagini recente » Cod sursa (job #3181908) | Cod sursa (job #255496) | Cod sursa (job #1521077) | Borderou de evaluare (job #2912982) | Cod sursa (job #2653682)
#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
using namespace std;
vector<int> p, level, v;
int sq;
int lca(int x, int y) {
if (level[x] > level[y])
while (level[x] > level[y]) x = p[x];
else if (level[y] > level[x])
while (level[y] > level[x]) y = p[y];
while (x!=y) {
x = p[x];
y = p[y];
}
return x;
}
int mainLca(int x, int y) {
if(level[x]/sq > level[y]/sq)
while (level[x] / sq > level[y] / sq){
x = v[x];
}
else if (level[y] / sq > level[x] / sq)
while (level[y] / sq > level[x] / sq) {
y = v[y];
}
if (x == y) return x;
while (v[x] != v[y]) {
x = v[x];
y = v[y];
}
return lca(x, y);
}
int findNext(int root,int z) {
if (v[root] != -1) return v[root];
int l = level[root];
int zone = l / sq;
if (zone == z - 1)
return root;
v[root] = findNext(p[root], z);
return v[root];
}
int findLevel(int root) {
if (level[root] != -1) return level[root];
level[root] = findLevel(p[root]) + 1;
return level[root];
}
int main() {
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m;
fin >> n >> m;
p.resize(n + 1, -1);
level.resize(n + 1, -1);
v.resize(n + 1, -1);
for (int i = 2;i <= n;++i) {
int x;
fin >> x;
p[i] = x;
}
level[1] = 1;
sq = 0;
for (int i = 2;i <= n;++i) {
findLevel(i);
if (level[i] > sq) sq = level[i];
}
v[1] = 0;
for (int i = 2;i <= n;++i)
findNext(i, level[i] / sq);
sq = sqrt(sq);
while (m--) {
int x, y;
fin >> x >> y;
fout << mainLca(x, y) << '\n';
}
return 0;
}