Pagini recente » Cod sursa (job #2946052) | Cod sursa (job #2882879) | Cod sursa (job #2537129) | Cod sursa (job #726472) | Cod sursa (job #1930358)
#include <fstream>
#include <vector>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
const int NMAX = 100002;
vector <int> G[NMAX];
int Euler_List[NMAX << 1], cnt_euler; //parcurgerea Euler a grafului
int Level[NMAX << 1]; //nivelul corespunzator nodului din parcurgerea lui Euler
int First_Poz[NMAX]; //memoreaza prima aparitie a nodului i
int Lg[NMAX << 1];
int RMQ[NMAX << 1][19]; //RMQ[i][j] - nodul de nivel minim corespunzator secventei [i, i + 2^j - 1] din reprezentarea lui Euler a arborelui
int N, M;
void DFS(int node, int level)
{
First_Poz[node] = ++cnt_euler;
Euler_List[cnt_euler] = node;
Level[cnt_euler] = level;
for (const int & x : G[node])
{
DFS(x, level + 1);
Euler_List[++cnt_euler] = node;
Level[cnt_euler] = level;
}
}
void RMQ_process()
{
for (int i = 1; i <= cnt_euler; ++i)
RMQ[i][0] = i;
for (int j = 1; (1 << j) < cnt_euler; ++j)
for (int i = 1; i + (1 << j) <= cnt_euler; ++i)
if (Level[RMQ[i][j - 1]] < Level[RMQ[i + (1 << (j - 1))][j - 1]])
RMQ[i][j] = RMQ[i][j - 1];
else
RMQ[i][j] = RMQ[i + (1 << (j - 1))][j - 1];
for (int i = 2; i <= cnt_euler; ++i)
Lg[i] = Lg[i >> 1] + 1;
}
int solve(int u, int v)
{
//Lca(u, v) va fi nodul de nivel minim din secventa First[u], First[v]
int a = First_Poz[u], b = First_Poz[v];
if (a > b) //avem nevoie de un interval "real"
swap(a, b);
int k = Lg[b - a + 1];
if (Level[RMQ[a][k]] < Level[RMQ[b + (1 - (1 << k))][k]])
return Euler_List[RMQ[a][k]];
else
return Euler_List[RMQ[b + (1 - (1 << k))][k]];
}
int main()
{
f >> N >> M;
for (int i = 2; i <= N; ++i)
{
int x;
f >> x;
G[x].push_back(i);
}
DFS(1, 0);
RMQ_process();
for (int i = 1; i <= M; ++i)
{
int u, v;
f >> u >> v;
g << solve(u, v) << "\n";
}
f.close();
g.close();
return 0;
}