Cod sursa(job #3254190)

Utilizator ALEXANDRUspargoaseAlexandru Joita ALEXANDRUspargoase Data 6 noiembrie 2024 14:17:31
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.14 kb
#include <fstream>
#include <iostream>
#include <vector>

using namespace std;
ifstream in ("lca.in");
ofstream out ("lca.out");

const int NMAX = 1e5;
int n,q;
int log[NMAX], A[18][NMAX], rang[NMAX];
vector<int> G[NMAX];

void precalc() {
    //precalc log intreg in baza 2
    for (int i = 2; i <= n; i++)
        log[i] = log[i/2] + 1;

    //precalc matricea tatiilor de oridin 2^k, unde a[j][i] este al 2^j lea stramos al lui i
    for (int j = 1; (1 << j) <= n; j++)
        for (int i = 1; i <= n; i++) {
                  A[j][i] = A[j-1][A[j-1][i]]; //adica stramosul stramosului de ordin 2^k
        }

}

void printMat (int A[][NMAX]) {
    for (int i = 0; (1 << i) <= n; i++, cout << '\n')
        for (int j = 1; j <= n; j++)
            cout << A[i][j]<< " ";
    /* n = 11, stramosi de grad 2^k
        0 1 1 2 2 2 4 4 6 3 3
        0 0 0 1 1 1 2 2 2 1 1
        0 0 0 0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0 0 0 0
    */
}

void dfs(int nod, int lev)
{
    //dfs initial pentru rangul fiecarui nod in arbore
    rang[nod] = lev;

    for (auto v: G[nod])
        dfs(v, lev+1);
}

int lca(int x, int y)
{
	if(rang[x] < rang[y])
		swap(x, y);

    // lifting y to x
	int log1, log2;
	for(log1 = 1; (1 << log1) < rang[x]; ++log1);
	for(log2 = 1; (1 << log2) < rang[y]; ++log2);

	for(int k = log1; k >= 0; --k)
		if(rang[x] - (1 << k) >= rang[y])
			x = A[k][x];

	if(x == y) return x;


	/*
    de la acelasi nivel, lift amandoi pana gasim stramosi comun
	Se formeaza o suma crescatoare din puteriile lui 2 incercand sa maximizam pasii
	*/
	for(int k = log2; k >= 0; --k)
		if(A[k][x] && A[k][x] != A[k][y])
			x = A[k][x],
			y = A[k][y];

	return A[0][x];
}

int main()
{
    in >> n >> q;
    for (int i = 2; i <= n; i++) { //radaina este specificata, anume 1
        in >> A[0][i]; //citim prima linie de stramosi
        G[A[0][i]].push_back(i); //abore orientat cu susul in jos (sensul parcurgerii dfs)
    }

    precalc();
    dfs(1, 0);

    for(int x, y; q; q--)
    {
        in >> x >> y;
        out << lca(x, y) << "\n";
    }

    printMat(A);

    return 0;
}