Cod sursa(job #1455596)

Utilizator GilgodRobert B Gilgod Data 28 iunie 2015 16:26:05
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.55 kb
#include <iostream>
#include <fstream>
#include <assert.h>
#include <cmath>

const char IN[] = "rmq.in", OUT[] = "rmq.out";
const int NMAX = 100000;
const int LOGNMAX = 17;

inline int min(int a, int b) { return (a) < (b) ? (a) : (b); }

using namespace std;

int N, M;
int A[NMAX];
int PRE[NMAX - 1][LOGNMAX];

inline void preprocess() {
	//PRE[i][j] = indexul minimului pe portiunea ce incepe la i si are dimensiune 2^j
	//C.B. j = 0
	for (int i = 0; i < N; ++i) PRE[i][0] = i;
	//de la intervale mai mici la mai mari
	for (int j = 1; (1 << j) < N; ++j) {
		for (int i = 0; i + (1 << j) - 1 < N; ++i) {
			//minimul din intervalul din stanga (i,2^(j-1)-1) si cel din dreapta
			if (A[PRE[i][j - 1]] < A[PRE[i + (1 << (j - 1))][j - 1]])
				PRE[i][j] = PRE[i][j - 1];
			else PRE[i][j] = PRE[i + (1 << (j - 1))][j - 1];
		}
	}
}

inline void read_data() {
	assert(freopen(IN, "r", stdin));
	assert(freopen(OUT, "w", stdout));
	assert(scanf("%d %d", &N, &M));
	for (int i = 0; i < N; ++i) assert(scanf("%d", &A[i]));
	preprocess();
	for (int i = 0; i < M; ++i) {
		int x, y;
		assert(scanf("%d %d", &x, &y));
		--x, --y;
		int size = y - x + 1;
		int interval = (int)log2(size);
		//intervalul e impartit acum in doua: x..(x+(2^interval)-1)
		//si y-(2^interval)..y+(2^interval)-1. Cele doua intervale 
		//acopera [x,y] si se suprapun complet daca [y-x+1] = 2^z
		printf("%d\n", min(A[PRE[x][interval]], A[PRE[y - (1 << interval) + 1][interval]]));
	}
	fclose(stdout);
	fclose(stdin);
}

int main() {
	read_data();
	return 0;
}