Cod sursa(job #2055255)

Utilizator mlc_oficialBoris Barca mlc_oficial Data 2 noiembrie 2017 23:28:59
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.04 kb
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <iostream>
#include <numeric>
#include <vector>
#include <fstream>

using namespace std;

template<class T, typename Compare = less<T>>
class RangeMinimumQuery {
public:
    RangeMinimumQuery() { }
    RangeMinimumQuery(const vector<T>& _v) : v(_v) {
        int n = static_cast<int>(v.size());
        InitLogarithm(n+1);  
        InitTable(__lg(n-1) + 1, n);
    }
    
    int Query(int left, int right) const {
        const int log_length = logarithm[right - left + 1];
        return MinIdx(sparse_table[log_length][left],
                      sparse_table[log_length][right - (1 << log_length) + 1]);
    }
private:
    vector<vector<int>> sparse_table;
    vector<int> logarithm;
    vector<T> v;
    
    int MinIdx(const int a, const int b) const {
        return Compare()(v[a], v[b]) ? a : b;    
    }
    
    void InitLogarithm(int max_size) {
        logarithm.resize(max_size);
        logarithm[1] = 0;
        for (int i = 2; i < max_size; i += 1) {
            logarithm[i] = 1 + logarithm[i >> 1];
        }
    }
    
    void InitTable(int h, int n) {
        sparse_table.resize(h);
        for (auto& row : sparse_table) {
            row.resize(n);
        }
        iota(sparse_table[0].begin(), sparse_table[0].end(), 0);
        for (int i = 1; i < h; i += 1) {
            for (int j = 0; j + (1 << i) <= n; j += 1) {
                sparse_table[i][j] = MinIdx(sparse_table[i - 1][j], 
                                            sparse_table[i - 1][j + (1 << (i - 1))]);
            }
        }
    }
};

int main() {
    ifstream cin("rmq.in");
    ofstream cout("rmq.out");
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    
    int n, q; cin >> n >> q;
    vector<int> v(n);
    for (auto& x : v) {
        cin >> x;
    }
    
    RangeMinimumQuery<int> rmq(v);
    while (q--> 0) {
        int left, right; cin >> left >> right; left -= 1; right -= 1;
        cout << v[rmq.Query(left, right)] << '\n';
    }
    return 0;
}