Cod sursa(job #2605561)

Utilizator borscalinCalin-Stefan Georgescu borscalin Data 25 aprilie 2020 14:01:35
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.09 kb
#include <iostream>
#include <fstream>
#include <vector>

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

const int NMAX = 100000;
const int LGMAX = 20;

int father[1 + NMAX];
int level[1 + 2 * NMAX];
int v[1 + 2 * NMAX];
int first[1 + NMAX];
int l;
std::vector <int> edges[1 + NMAX];

void euler ( int node ) {
    v[++l] = node;
    first[node] = l;
    level[node] = 1 + level[father[node]];
    for ( int i = 0; i < edges[node].size(); ++i ) {
        int newNode = edges[node][i];
        euler ( newNode );
        v[++l] = node;
    }
}

class RMQ {
	private : 
		short logs[1 + 2 * NMAX];
		int rmq[LGMAX][2 * NMAX];
 
	public :
		void calculateLogs ( int N ) {
			logs[1] = 0;
			for ( int i = 2; i <= N; ++i ) 
				logs[i] = 1 + logs[i / 2];
		}
 
	public :
		void calculateRMQ ( int N ) {
			for ( int i = 1; i <= N; ++i )
				rmq[0][i] = i;
 
			for ( int i = 1; i <= logs[N]; ++i ) {
				for ( int j = 0; j <= N; ++j ) {
					int st = rmq[i][j] = rmq[i - 1][j - ( 1 << ( i - 1 ) )];
                    int dr = rmq[i - 1][j];
                    if ( level[v[st]] > level[v[dr]] )
                        rmq[i][j] = dr;
                    else
                        rmq[i][j] = st;
                }
            }
		}
	public : 
		int minInterval ( int left, int right ) {
			int l = logs[right - left + 1];
            int st = rmq[l][left + ( 1 << l ) - 1];
            int dr = rmq[l][right];
			if ( level[v[st]] <= level[v[dr]] )
                return v[st];
            return v[dr];
		}
};

RMQ rmq = RMQ();

int lca ( int x, int y ) {
    int p = first[x];
    int q = first[y];
    if ( p > q )
        std::swap ( p, q );
    return rmq.minInterval ( p, q );
}

int main() {

    int N, M;

    fin >> N >> M;

    for ( int i = 2; i <= N; ++i ) {
        fin >> father[i];
        edges[father[i]].push_back ( i );
    }

    euler ( 1 );

    rmq.calculateLogs ( 2 * N - 1 );
    rmq.calculateRMQ ( 2 * N - 1 );

    for ( int i = 1; i <= M; ++i ) {
        int x, y;
        fin >> x >> y;
        fout << lca ( x, y ) << '\n';
    }

    fin.close();
    fout.close();

    return 0;
}