Cod sursa(job #2096422)

Utilizator belgun_adrianBelgun Dimitri Adrian belgun_adrian Data 29 decembrie 2017 10:02:21
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.6 kb
#include <fstream>
#include <vector>
#include <algorithm>

namespace Util {
	int log2_ls(int x) {
		for (int i = 0; i < 32; i++)
			if (x < (1 << (i + 1)))
				return i;
		return -1;
	}

	int log2_bs(int x) {
		int l = 0;
		int r = 31;

		int m;
		while (l <= r) {
			m = (l + r) / 2;
			if ((x >= (1 << m)) && (x < (1 << (m + 1))))
				return m;
			if (x < (1 << m))
				r = m;
			else
				l = m;
		}
		return -1;
	}
}

class RMQ {
public:
	RMQ(const std::vector<int>& _v) : v(_v), mins(20, std::vector<int>(v.size())) {
		build();
	}

	int min(int a, int b) {
		if (a > b)
			std::swap(a, b);
		int delta = b - a + 1;
		int log_delta = Util::log2_bs(delta);
		if (v[mins[log_delta][a]] < v[mins[log_delta][b - (1 << log_delta) + 1]])
			return mins[log_delta][a];
		else 
			return mins[log_delta][b - (1 << log_delta) + 1];
	}

private:
	const std::vector<int>& v;
	std::vector<std::vector<int>> mins;
	void build() {
		int n = v.size();
		for (int i = 0; i < n; i++) 
			mins[0][i] = i;
		for (int j = 1; (1 << j) <= n; j++)
			for (int i = 0; i + (1 << j) - 1 < n; i++)
				if (v[mins[j - 1][i]] < v[mins[j - 1][i + (1 << (j - 1))]])
					mins[j][i] = mins[j - 1][i];
				else
					mins[j][i] = mins[j - 1][i + (1 << (j - 1))];
	}
};

int main() {
	std::ifstream in("rmq.in");
	std::ofstream out("rmq.out");

	int n, m;
	in >> n >> m;

	std::vector<int> v(n);
	for (int i = 0; i < n; i++) {
		int x;
		in >> x;
		v[i] = x;
	}

	RMQ q(v);
	for (int i = 0; i < m; i++) {
		int a, b;
		in >> a >> b;
		out << v[q.min(a - 1, b - 1)] << "\n";
	}
	return 0;
}