Cod sursa(job #2635244)

Utilizator k2e0e0w3qDumitrescu Gheorghe k2e0e0w3q Data 13 iulie 2020 19:38:21
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.4 kb
#include <fstream>
#define N 100000
using namespace std;

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 log (int x) {
    return 31 - __builtin_clz(x);
}

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) {
    ifstream fin ("rmq.in");
    ofstream fout ("rmq.out");

    int n, m, i;
    fin >> n >> m;
    for (i=0; i<n; ++i)
        fin >> 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) {
        fin >> x >> y;
        --x;
        --y;
        fout << query(x, y) << '\n';
    }
    return 0;
}