Cod sursa(job #1786642)

Utilizator RobertSSamoilescu Robert RobertS Data 23 octombrie 2016 13:58:59
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 1.86 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>


using namespace std;


int const MAX_N = 100001;
int const MAX_M = 2000001;

int const ROOT = 1; //radacina


int N, M; //numarul de noduri, numarul de queries
vector<int> graph[MAX_N]; //reprezentarea grafului prin liste
vector<int> euler_rep; //reprezentarea euler cu noduri
vector<int> depth_rep; //reprezentare euler cu adancimi

int pos_node[MAX_N]; //pozitia fiecarui nod in reprezentarea euler


void DFS(int node, int depth) {
		
	euler_rep.push_back(node);
	depth_rep.push_back(depth);
	pos_node[node] = depth_rep.size() - 1;
	
	for (size_t i = 0; i < graph[node].size(); i++) {
		DFS(graph[node][i], depth + 1);
		depth_rep.push_back(depth);
		euler_rep.push_back(node);
		
	}

}

int rmq[3 * MAX_N][25];

void RMQ() {

	int rows = depth_rep.size();
	int cols = floor(log2(rows)) + 1;

	//cout << rows << " " << cols << endl;

	for (size_t i = 0; i < depth_rep.size(); i++) {
		rmq[i][0] = i;
	}

	for (int j = 1; j < cols; j++) {
		for (int i = 0; (i + (1 << j) - 1) < rows; i++) {
			int step = 1 << (j - 1);
			int index1 = rmq[i][j - 1];
			int index2 = rmq[i+step][j - 1];

			if (depth_rep[index1] < depth_rep[index2])
				rmq[i][j] = index1;
			else
				rmq[i][j] = index2;

		}		
	}

}

int query_RMQ(int x, int y) {
	int li = min(x, y);
	int ls = max(x, y);


	int len = ls - li + 1;
	int step= floor(log2(len));
	int rem = len - (1 << step);

	return euler_rep[min(rmq[li][step], rmq[li+rem][step])];
}

int main() {

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



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

	DFS(ROOT, 0);

	RMQ();

	for (int i = 0; i < M; i++) {
		int node1, node2;
		fin >> node1 >> node2;
		fout << query_RMQ(pos_node[node1], pos_node[node2]) << '\n';
	}

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

	return 0;
}