Cod sursa(job #3253689)

Utilizator Vlad_NistorNIstor Vlad Vlad_Nistor Data 4 noiembrie 2024 11:54:51
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.61 kb
#include <bits/stdc++.h>
using namespace std;

const int MAXP = 20, NMAX = 100001;

int rmq[MAXP][NMAX], Log[NMAX];

void precalcMinims(int n){
    for(int put = 1; (1 << put) <= n; put++){
        for(int i = 1; i <= n;i++){
            rmq[put][i] = rmq[put-1][i];
            int right = i + (1<<(put-1));
            /// minimul este minimul dintre  diagonala ori la urmatoarea secventa putere de doi anterioara

            if(right <= n && rmq[put-1][right] < rmq[put][i]){
                rmq[put][i] = rmq[put-1][right];
            }
        }
    }
    /// putem calcula exponentii direct din precalculare pentru a ne fi mult mai usor sa computam rezultatul si a nu mai folosii cautare binara
    for(int i = 2;i <= n;i++){
        Log[i] = Log[i / 2] + 1;
    }
}

int32_t getMinim(int left, int right){
    /// trebuie sa incadram intervalul nostru intre doua puteri, doua intervale de puteri de 2 de aceea ne si trebuie
    /// calculat exponentul
    int exponent = Log[right - left + 1];
    int lenght = (1 << exponent);
    return min(rmq[exponent][left], rmq[exponent][right - lenght + 1]);
}

int32_t main(void){
    ofstream cout("rmq.out");
    ifstream cin("rmq.in");
    int n, Q;
    cin >> n >> Q;
    for(int i = 1;i <= n;i++){
        cin >> rmq[0][i]; /// practic minimul pentru secventa de 2 ^ 0 = 1 este fix el insusi astfel ne putem permite\
        // al initializa direct din citire
    }

    /// !! precalculam
    precalcMinims(n);

    /// Querys
    while(Q--){
        int st, dr;
        cin >> st >> dr;
        cout << getMinim(st, dr) << '\n';
    }
}