Cod sursa(job #3037850)

Utilizator AlexNeaguAlexandru AlexNeagu Data 26 martie 2023 16:04:48
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.52 kb
#include<iostream>
#include<fstream>
using namespace std;

ifstream in("rmq.in");
ofstream out("rmq.out");
#define cin in  
#define cout out  

const int nmax = 100005;
const int L = 18;

int n, m;
int a[nmax];
int dp[nmax][L];
int logaritm[nmax];

// dp[i][j] - raspunsul minim pentru intervalul de lungime 2^j care incepe din i

int getMin(int l, int r) {
	int lungimeInterval = r - l + 1;
	int log = logaritm[lungimeInterval];
	// pot sa impart intervalul l..r in doua subintervale:
	// 		intervalul care incepe cu l si are lungimea 2 ^ log 
	//      intervalul care incepe cu r - (2^log) + 1 si are lungimea 2 ^ log
	return min(dp[l][log], dp[r - (1 << log) + 1][log]);
}

int main() {
	logaritm[1] = 0;
	for(int i = 2; i < nmax; ++i) {
		logaritm[i] = logaritm[i / 2] + 1;
	}

	cin >> n >> m;
	for(int i = 1; i <= n; ++i) {
		cin >> a[i];
	}
	for(int i = 1; i <= n; ++i) {
		dp[i][0] = a[i];
		// raspunsul minim pe intervalul de lungime 2^0 care incepe din i este a[i]
	}

	for(int exp = 1; exp < L; exp++) {
		for(int i = 1; i + (1 << exp) - 1 <= n; ++i) {
			// intervalul de lungime 2^exp care incepe din i 
			// stiu ca intervalul asta are doua jumatati: 
			// 							   un interval de lungime 2^(exp - 1) care incepe la i
			// 							   un interval de lungime 2^(exp - 1) care incepe in i + 2^(exp-1)
			int halfLen = 1 << (exp - 1);
			dp[i][exp] = min(dp[i][exp - 1], dp[i + halfLen][exp - 1]);
		}
	}

	while(m--) {
		int l, r;
		cin >> l >> r;
		cout << getMin(l, r) << '\n';
	}
}