Cod sursa(job #884329)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 20 februarie 2013 21:04:17
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.51 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 Step = 1, Length = 2; Length <= N; ++Step, Length *= 2) {
        for (int i = 1; i + Length - 1 <= N; ++i) {
            if (Compare(RMQ[Step - 1][i], RMQ[Step - 1][i + Length / 2]))
                RMQ[Step][i] = RMQ[Step - 1][i];
            else
                RMQ[Step][i] = RMQ[Step - 1][i + Length / 2];
        }
    }
}

inline int Query(const int Left, const int Right) {
    int Step = Log[Right - Left + 1], Length = 1 << Log[Right - Left + 1];
    if (Compare(RMQ[Step][Left], RMQ[Step][Right - Length + 1]))
        return RMQ[Step][Left];
    else
        return RMQ[Step][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;
}