Pagini recente » Cod sursa (job #2782509) | Cod sursa (job #1675756) | Cod sursa (job #3260270) | Cod sursa (job #843781) | Cod sursa (job #2908317)
#include <fstream>
#include <iostream>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
const int N = 1e5 + 1, LOG = 17;
int n, m, x, y;
int log[N], nivel[N], t[LOG][N]; // t[e][i] = al 2^e-lea stramos as lui i
void nivelul(int nod){
if(nivel[nod])
return;
nivelul(t[0][nod]);
nivel[nod] = nivel[t[0][nod]] + 1;
}
void calculeaza(){
for(int i = 2; i <= n; i++)
log[i] = 1 + log[i / 2];
for(int e = 1; e < LOG; e++){
for(int i = 1; i <= n; i++){
t[e][i] = t[e - 1][t[e - 1][i]];
}
}
nivel[1] = 1; // 1 e radacina
for(int i = 2; i <= n; i++)
nivelul(i);
}
// returneaza stramosul de un anumit ordin al lui x
int stramos(int x, int ordin){
/*while(ordin--) -------------------- dar asta e O(ordin) si putem face O(log2(ordin))
x = t[0][x];*/
int e = 0;
while(ordin){
if(ordin % 2)
x = t[e][x];
e++;
ordin /= 2;
}
return x;
}
int lca(int x, int y){
int e = log[nivel[x]]; // nivel[x] == nivel[y]
while(e >= 0){
if(t[e][x] != t[e][y]){
x = t[e][x];
y = t[e][y];
}
e--;
}
return t[0][x]; // stiu ca t[0][x] == t[0][y]
}
int main(){
f >> n >> m;
for(int i = 2; i <= n; i++)
f >> t[0][i];
calculeaza();
while(m--){
f >> x >> y;
if(nivel[x] > nivel[y])
swap(x, y);
y = stramos(y, nivel[x] - nivel[y]);
if(x == y){
g << x << '\n';
continue;
}
g << lca(x, y) << '\n';
}
f.close();
g.close();
}