Cod sursa(job #1127576)

Utilizator fhandreiAndrei Hareza fhandrei Data 27 februarie 2014 12:57:52
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.54 kb
// Include
#include <fstream>
using namespace std;

// Constante
const int sz = (int)1e5+1;

// Variabile
ifstream in("rmq.in");
ofstream out("rmq.out");

int num, questions;

int LG[sz]; // LG[i] e partea intreaga a logaritmului in baza 2 din i, precalculat
int RMQ[18][sz]; // RMQ[i][j] e minimul de pe intervalul ce incepe in j si are lungime 2^i

// Main
int main()
{
	in >> num >> questions;
	
	// Pe linia 0, lungimea intervalului va fi 2^0=1, deci inputul
	for(int i=1 ; i<=num ; ++i)
		in >> RMQ[0][i];
	
	// Fiind puteri a lui 2, LG[i] este, mereu, cu 1 mai mare decat LG[i/2]
	for(int i=2 ; i<=num ; ++i)
		LG[i] = LG[i/2] + 1;
	
	// Construiesc matricea, linie cu linie, prin calcularea minimului dintre 2 intervale cu lungimi egale si cu lungimea
	// egala cu jumatate din lungimea intervalului curent (lungimile, fiind puteri ale lui 2, vor fi pe linii consecutive)
	for(int i=1 ; 1<<i<=num ; ++i)
	// La sfarsitul liniei, capatul din dreapta al intervalului va depasi numarul de elemente, asa ca ma oproesc mai repede
		for(int j=1 ; j<=num-(1<<i)+1; ++j)
			RMQ[i][j] = min(RMQ[i-1][j], RMQ[i-1][j+(1<<(i-1))]);
	
	// Intervalele primite ca interogari
	int left, right;
	
	while(questions--)
	{
		in >> left >> right;
		// Lungimea intervalului cautat este right-left+1
		int line = LG[(right-left+1)];
		
		// Formez intervalul cautat ca reuniune de 2 intervale mai mici, uneori suprapuse
		out << min(RMQ[line][left], RMQ[line][right-(1<<line)+1]) << '\n';
	}
	
	in.close();
	out.close();
	return 0;
}