Pagini recente » Cod sursa (job #1735359) | Cod sursa (job #312754) | Cod sursa (job #3154300) | Cod sursa (job #1862213) | Cod sursa (job #2175139)
#include <iostream>
#include <fstream>
#include <vector>
#define DM 100005
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m, val, u, v, rmq[20][DM * 2], log[DM * 2], eul[DM * 2], dim, lvl[DM * 2], first[DM * 2];
vector <int> g[DM];
void dfs_euler(int nod, int level)
{
dim++;
eul[dim] = nod; // repr. euler a arb.
lvl[dim] = level; // nivelul nodului in arb.
first[nod] = dim; // prima aparitie a nodului in repr. euler a arb.
for(auto it : g[nod])
{
dfs_euler(it, level + 1);
dim++;
eul[dim] = nod;
lvl[dim] = level;
}
}
void build_rmq() // rmq[k][i] = pozitia nodului de nivel minim din secventa din repr. eul. a arb. ce incepe pe poz i si are lungime 2^k
{
log[0] = -1;
for(int i = 1; i <= dim; i++)
{
log[i] = 1 + log[i / 2];
rmq[0][i] = i;
}
for(int k = 1; k <= log[dim]; k++)
for(int i = 1; i + (1 << k) - 1 <= dim; i++)
{
int l = (1 << (k - 1));
if(lvl[ rmq[k - 1][i] ] < lvl[ rmq[k - 1][i + l] ])
rmq[k][i] = rmq[k - 1][i];
else rmq[k][i] = rmq[k - 1][i + l];
}
}
int lca(int u, int v) //Cel mai apropiat strămoş comun a 2 noduri este nodul de nivel minim dintre primele apariţii ale nodurilor din query din reprezentarea Euler a arborelui.
{
u = first[u];
v = first[v];
if(u > v)
swap(u, v);
int l = log[v - u + 1];
if(lvl[ rmq[l][u] ] < lvl[ rmq[l][v - (1 << l) + 1] ])
return eul[ rmq[l][u] ];
else return eul[ rmq[l][v - (1 << l) + 1] ];
}
int main()
{
fin >> n >> m;
for(int i = 1; i < n; i++)
{
fin >> val;
g[val].push_back(i + 1); // arborele
}
dfs_euler(1, 0);
build_rmq();
for(int i = 1; i <= m; i++)
{
fin >> u >> v;
fout << lca(u, v) << '\n';
}
return 0;
}