Cod sursa(job #884324)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 20 februarie 2013 21:02:23
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.47 kb
#include <cstdio>
#include <cassert>

#include <algorithm>

using namespace std;

const int MAX_N = 100005;
const int MAX_LOG = 18;

int N, Values[MAX_N], Log[MAX_N], RMQ[MAX_LOG][MAX_N];

inline bool Compare(const int X, const int Y) {
    return Values[X] < Values[Y];
}

void BuildLog() {
    for (int i = 2; i <= N; ++i)
        Log[i] = Log[i / 2] + 1;
}

void BuildRMQ() {
    BuildLog();
    for (int i = 1; i <= N; ++i)
        RMQ[0][i] = i;
    for (int l = 1, length = 2; length <= N; ++l, length *= 2) {
        for (int i = 1; i + length - 1 <= N; ++i) {
            if (Compare(RMQ[l - 1][i], RMQ[l - 1][i + length / 2]))
                RMQ[l][i] = RMQ[l - 1][i];
            else
                RMQ[l][i] = RMQ[l - 1][i + length / 2];
        }
    }
}

inline int Query(const int left, const int right) {
    int l = Log[right - left + 1], length = 1 << Log[right - left + 1];
    if (Compare(RMQ[l][left], RMQ[l][right - length + 1]))
        return RMQ[l][left];
    else
        return RMQ[l][right - length + 1];
}

int main() {
    assert(freopen("rmq.in", "r", stdin));
    assert(freopen("rmq.out", "w", stdout));
    int M; assert(scanf("%d %d", &N, &M) == 2);
    for (int i = 1; i <= N; ++i)
        assert(scanf("%d", &Values[i]) == 1);
    BuildRMQ();
    for (; M > 0; --M) {
        int left, right; assert(scanf("%d %d", &left, &right) == 2);
        printf("%d\n", Values[Query(left, right)]);
    }
    return 0;
}