Pagini recente » Borderou de evaluare (job #2568442) | Cod sursa (job #1690513) | Cod sursa (job #1690571)
#include <fstream>
#include <vector>
using namespace std;
const int MAXN = 100005;
const int MAXP = 20;
const int MAXEULER = MAXN * 2;//fiecare nod apare in jur de doua ori in reprezentare
ifstream in("lca.in");
ofstream out("lca.out");
int n;
vector<int> fii[MAXN];
int rmq[MAXP][MAXEULER * 2];//cel mai mic numar din intervalul j, j + 2 ^ i - 1
int lmax[MAXEULER];
int euler[MAXEULER], nivel[MAXEULER], primul[MAXN];
int l_euler = 0;
void citire()
{
int tata;
for (int i = 2;i <= n;++i)
{
in >> tata;
fii[tata].push_back(i);
}
}
void dfs(int nod, int niv)
{
++l_euler;
euler[l_euler] = nod;
nivel[l_euler] = niv;
primul[nod] = l_euler;
for (unsigned int i = 0; i < fii[nod].size();++i)
{
dfs(fii[nod][i], niv + 1);
++l_euler;
euler[l_euler] = nod;
nivel[l_euler] = niv;
}
}
void preprocesare()
{
//generare reprezentare euler
dfs(1,0);
//calculare rmq
lmax[1] = 0;
for (int i = 2;i <= l_euler;++i)
lmax[i] = lmax[i / 2] + 1;
for (int i = 1;i <= l_euler;++i)
rmq[0][i] = i;
for (int i = 1;(1 << i) < l_euler;++i)
for (int j = 1;j <= l_euler - (1 << i);++j)
{
int l = 1 << (i - 1);
rmq[i][j] = rmq[i - 1][j];
if (nivel[rmq[i][j]] > nivel[rmq[i - 1][j + l]])
rmq[i][j] = rmq[i - 1][j + l];
}
}
int lca(int a, int b)
{
a = primul[a];
b = primul[b];
if (b < a)
swap(a,b);
int lung = b - a + 1;
int l = lmax[lung];
int poz1 = a, poz2 = a + lung - (1 << l);
int sol = rmq[l][poz1];
if (nivel[sol] > nivel[rmq[l][poz2]])
sol = rmq[l][poz2];
return euler[sol];
}
int main()
{
int m;
in >> n >> m;
citire();
preprocesare();
for (int i = 1;i <= m;++i)
{
int x,y;
in >> x >> y;
out << lca(x, y) << '\n';
}
return 0;
}