Cod sursa(job #2312461)

Utilizator dragomir_ioanDragomir Ioan dragomir_ioan Data 4 ianuarie 2019 21:25:28
Problema Range minimum query Scor 100
Compilator c-64 Status done
Runda Arhiva educationala Marime 1.5 kb
/*
 * Range Minimum Query
 * https://infoarena.ro/problema/rmq
 *
 */

#include <stdio.h>

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

int n;
int logn;
int mintable[18][100001]; // un pic peste log n

/*
 * E interesant un comm de pe infoarena care zice ca [18][100001] e mai bine
 * decat [100001][18] pentru ca de obicei accesezi pozitii consecutive de pe
 * aceeasi linie, nu linii diferite de la aceeasi coloana. Si cacheurilor le
 * place cand ai chestiile pe care le accesezi des cat mai apropiate
 *
 */

inline void rmq_init() {
	for(int spacing=1; spacing < logn; spacing++) {
		int lastjmp = 1 << (spacing-1);
		for(int i=1; i<=n-lastjmp; i++) {
			mintable[spacing][i] = Min(mintable[spacing-1][i], mintable[spacing-1][i + lastjmp]);
		}
	}
}


inline int rmq_query(int st, int dr) {
	int dist = dr - st + 1;
	int spacing = logn;
	while(spacing > 0 && (1 << spacing) >= dist) spacing--;

	//fprintf(stderr, "[%d, %d] cu log(%d)=%d -> iau [%d,%d] si [%d,%d]\n",
	//	st, dr, dist, spacing, st, st+(1<<spacing)-1, dr - (1<<spacing) + 1, dr - (1<<spacing) + 1 + (1<<spacing)-1);

	return Min(mintable[spacing][st], mintable[spacing][dr - (1<<spacing) + 1]);
}

int main() {
	freopen("rmq.in", "r", stdin);
	freopen("rmq.out", "w", stdout);

	int m;

	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) scanf("%d", &mintable[0][i]);

	logn = 0;
	while((1 << logn) <= n) logn++;

	rmq_init();

	for(int i=1; i<=m; i++) {
		int st, dr;
		scanf("%d%d", &st, &dr);
		printf("%d\n", rmq_query(st, dr));
	}

	return 0;
}