Cod sursa(job #2312437)

Utilizator dragomir_ioanDragomir Ioan dragomir_ioan Data 4 ianuarie 2019 20:58:46
Problema Range minimum query Scor 60
Compilator c-64 Status done
Runda Arhiva educationala Marime 1.33 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, res = 999999999;
	for(int spacing=logn; spacing>=0; spacing--) {
		if(dist & (1 << spacing)) {
			res = Min(res, mintable[spacing][st]);
			st += 1 << spacing;
		}
	}

	return res;
}

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;
}