Cod sursa(job #2635242)

Utilizator k2e0e0w3qDumitrescu Gheorghe k2e0e0w3q Data 13 iulie 2020 19:34:55
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.43 kb
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 100000
#define log(x) 31 - __builtin_clz(x)

static const int b = 30;
int n, v[N], seg[b+1][N], mask[N];
int cmp (int a, int b) {
    return v[a] < v[b] ? a : b;
}

int trans (int x, int base = b) {
    return x - (log(mask[x] & ((1 << base) - 1)));
}

int query (int x, int y) {
    if (y - x + 1 <= b)
        return v[trans(y, y-x+1)];
    int ans = cmp(trans(x + b - 1), trans(y));

    x /= b; ++x;
    y /= b; --y;
    if (x <= y) {
        int lg = log(y-x+1);
        ans = cmp(ans, cmp(seg[lg][x], seg[lg][y - (1<<lg) + 1]));
    }
    return v[ans];
}
int main (void) {
    freopen("rmq.in", "r", stdin);
    freopen("rmq.out", "w", stdout);

    int n, m, i;
    scanf("%d%d", &n, &m);
    for (i=0; i<n; ++i)
        scanf("%d", v+i);

    int at = 0;
    for (i=0; i<n; ++i) {
        at = (at << 1) & ((1<<b) - 1);
        while (at && cmp(i, i - __builtin_ctz(at)) == i)
            at ^= at & -at;
        at |= 1;
        mask[i] = at;
    }

    n/=b;
    for (i=0; i<n; ++i)
        seg[0][i] = trans(b*i + b - 1);

    int j;
    for (j=1; (1<<j) <= n; ++j)
        for (i=0; i + (1<<j) <= n; ++i)
            seg[j][i] = cmp(seg[j-1][i], seg[j-1][i + (1<<j-1)]);

    int x, y;
    for (; m; --m) {
        scanf("%d%d", &x, &y);
        --x;
        --y;
        printf("%d\n", query(x, y));
    }
    return 0;
}