Cod sursa(job #3164685)

Utilizator angelaAngela Visuian angela Data 4 noiembrie 2023 06:57:49
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.72 kb
// 381ms	
#include <bits/stdc++.h>
using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");

const int NMAX = 1e5 + 5, LOG = 25;
int n, m;
int N;                   // N = 2 * n - 1 - lungimea turului Euler
int E[2 * NMAX];         // nodurile parcurse in turul Euler  
int niv[2 * NMAX];       // niv[i] = nivelul in arbore al nodului E[i]
int poz[2 * NMAX];       // poz[x] = poz primei aparitii a lui x in turul Euler
int rmq[LOG][2 * NMAX];  // rmq[i][j] = pozitia in sirul E a nodului cu nivel minim in intervalul [j, j + 2^i]
vector<int> G[NMAX];

void CitesteArbore();
inline void DFS(int x, int h);
inline void RMQ();
inline int LCA(int x, int y);

int main()
{
    CitesteArbore();
    DFS(1, 0);
    RMQ();
	
	int x, y;
    while (m--)
	{
        fin >> x >> y;
		fout << LCA(x, y) << '\n';
    }
}

inline int LCA(int x, int y)
{
	int px = poz[x];
	int py = poz[y];
	if (px > py)
		swap(px, py);

	int k = log2(py - px + 1);

	if (niv[rmq[k][px]] < niv[rmq[k][py - (1 << k) + 1]])
		return E[rmq[k][px]];
		
	return E[rmq[k][py - (1 << k) + 1]];
}

inline void DFS(int x, int nv)
{
    E[++N] = x;
    niv[N] = nv;
    poz[x] = N;

    for(int y : G[x])
    {
        DFS(y, nv + 1);
        E[++N] = x;
        niv[N] = nv;
    }
}

inline void RMQ()
{
	for (int i = 1; i <= N; ++i)
		rmq[0][i] = i;
		
	int p1, p2;
    for (int i = 1; (1 << i) <= N; ++i)
        for (int j = 1; j <= N; ++j)
        {
			p1 = rmq[i - 1][j];
			p2 = rmq[i - 1][j + (1 << (i - 1))];
            if (niv[p1] < niv[p2])
                rmq[i][j] = p1;
            else
                rmq[i][j] = p2;
		}
}

void CitesteArbore()
{
	fin >> n >> m;
	
    for(int i = 2, tata; i <= n; ++i)
    {
        fin >> tata;
        G[tata].push_back(i);
    }
}