Cod sursa(job #2753433)

Utilizator truscalucaLuca Trusca truscaluca Data 22 mai 2021 20:55:11
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.9 kb
#include <iostream>

using namespace std;

const int nMax = 100005;

int v[nMax][17], log2[nMax];

int main() {
    freopen("rmq.in", "r", stdin);
    freopen("rmq.out", "w", stdout);

    // Input rapid
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;

    // Calculeaza toate valorile pentru log2(x) cu x in [1, nMax] - in O(nMax) (nu afecteaza complexitatea, din moment
    // ce construirea array-ului are complexitatea O(n logn) si trebuie sa mearga si cand n=nMax)
    log2[1] = 0;
    for (int i = 2; i <= nMax; i++) {
        log2[i] = log2[i / 2] + 1;
    }

    // Citeste toate numerele si pune-le in casuta 0 (ce semnifica faptul ca pentru urmatoarele 2^0=1 element,
    // minimul este x = numarul citit)
    for (int i = 1; i <= n; i++) {
        cin >> v[i][0];
    }

    // Parcurge numarul de salturi exponentiale posibile
    for (int p = 1; (1 << p) < n; p++) {

        // Parcurge toate numerele de la indecsii de la care se pot sari 2^p elemente
        for (int i = 1; i + (1 << p) - 1 <= n; i++) {

            // Urmatoarele 2^p elemente au minimul min(min din prima jumatate, min din a doua jumatate)
            v[i][p] = min(v[i][p - 1], v[i + (1 << (p - 1))][p - 1]);
        }
    }

    int st, dr;
    for (int q = 0; q < m; q++) {
        cin >> st >> dr;

        // Cate elemente sunt in intervalul [st, dr], in care trebuie cautat minimul
        int nr = dr - st + 1;

        // Minimul din intervalul [st, dr] este egal cu minimul dintre minimul intervalului [st,  2^(max posibil)] si
        // [dr - 2^(max posibil) + 1,  dr].
        //
        // A trebuit pus +1 pentru ca [2, 7] trebuie impartit in [2, 6] si [4, 7] (cand puterea maxima este 4),
        // nu [2, 4] si [3, 6] (ar fi uitat ultimul numar) - din moment ce in intervalul [a, b] sunt b-a+1 numere
        cout << min(v[st][log2[nr]], v[dr - (1 << log2[nr]) + 1][log2[nr]]) << "\n";
    }
}