Mai intai trebuie sa te autentifici.
Cod sursa(job #2648552)
Utilizator | Data | 11 septembrie 2020 14:05:45 | |
---|---|---|---|
Problema | Lowest Common Ancestor | Scor | 70 |
Compilator | cpp-64 | Status | done |
Runda | Arhiva educationala | Marime | 1.31 kb |
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
const int N = 100005;
const int LOG = 17;
int n, q;
int anc[LOG][N], d[N];
void computeDepth(int x)
{
if(anc[0][x] == 0 || d[x])
return;
if(d[anc[0][x]] == 0 && anc[0][x] != 0)
computeDepth(anc[0][x]);
d[x] = d[anc[0][x]] + 1;
}
void precompute()
{
for(int i = 1; i <= n; i++)
computeDepth(i);
for(int lvl = 1; (1 << lvl) <= n; lvl++)
for(int i = 1; i <= n; i++)
anc[lvl][i] = anc[lvl-1][anc[lvl-1][i]];
}
int solveQuery(int x, int y)
{
if(d[x] < d[y])
swap(x, y);
// aducerea pe acelasi nivel
int dif = d[x] - d[y];
for(int lvl = 0; (1 << lvl) <= n; lvl++)
if(dif & (1 << lvl))
x = anc[lvl][x];
// gasesc stramosul comun
if(x == y)
return x;
for(int lvl = LOG - 1; lvl >= 0; lvl--)
if(anc[lvl][x] != anc[lvl][y])
{
x = anc[lvl][x];
y = anc[lvl][y];
}
return anc[0][x];
}
int main()
{
fin >> n >> q;
for(int i = 2; i <= n; i++)
fin >> anc[0][i];
precompute();
while(q--)
{
int x, y;
fin >> x >> y;
fout << solveQuery(x, y) << '\n';
}
return 0;
}