Pagini recente » Cod sursa (job #2837641) | Cod sursa (job #178669) | Cod sursa (job #2136636) | Cod sursa (job #3277600) | Cod sursa (job #1936784)
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");
const int NMax = 1e5 + 5;
// precalculare in O(N) si raspuns pe query in (sqrt(H))
int N,M,H,root;
int dad[NMax],depth[NMax],ancestor[NMax];
vector<int> v[NMax];
// dad[i] = tatal nodului i
// depth[i] = adancimea la care se afla nodul i in arbore
// ancestor[i] = stramosul nodului i de pe nivelul inferior al bucatelei anterioare de sqrt(H) inaltime
void dfs(int,int);
// pentru a stabili inaltimea arborelui
void build(int);
// pentru a construi vectorul ancestor
int query(int,int);
// se gaseste un LCA in O(sqrt(H)) timp
int main() {
in>>N>>M;
for (int i=2;i<=N;++i) {
in>>dad[i];
v[dad[i]].push_back(i);
}
dfs(1,1);
for (root=1;root*root<=H;++root) ;
--root;
build(1);
while (M--) {
int a,b;
in>>a>>b;
out<<query(a,b)<<'\n';
}
return 0;
}
void dfs(int x,int d) {
depth[x] = d;
if (H < d) {
H = d;
}
vector<int>::iterator it;
for (it = v[x].begin();it < v[x].end();++it) {
dfs(*it,d+1);
}
}
void build(int x) {
if (depth[x] % root == 1) {
ancestor[x] = dad[x];
}
else {
ancestor[x] = ancestor[dad[x]];
}
vector<int>::iterator it;
for (it = v[x].begin();it < v[x].end();++it) {
build(*it);
}
}
int query(int x,int y) {
// daca x si y nu se afla in aceeasi bucatica de sqrt(H)
// se merge in sus de la nodul mai adanc, pe bucati de sqrt(H)
while (ancestor[x] != ancestor[y]) {
if (depth[x] > depth[y]) {
x = ancestor[x];
}
else {
y = ancestor[y];
}
}
while (depth[x] != depth[y]) {
if (depth[x] > depth[y]) {
x = dad[x];
}
else {
y = dad[y];
}
}
while (x != y) {
x = dad[x];
y = dad[y];
}
return x;
}