Cod sursa(job #2771432)

Utilizator RamanujanNeacsu Mihnea Ramanujan Data 27 august 2021 12:12:06
Problema Range minimum query Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.8 kb
#include <fstream>

using namespace std;

const int maxn=1e5+1;
const int powerOf2=18;

ifstream cin ("rmq.in");
ofstream cout ("rmq.out");

int a[maxn], interv[maxn][powerOf2], powers[powerOf2];//powers - puteri precalculate de 2
int n, m, lo, hi, floorPowerTwo[maxn];

int main(){
    cin>>n>>m;
    for(int i=0; i<n; i++){
        cin>>a[i];
    }
    powers[0]=1;
    int index=1;
    while(powers[index-1]<n){
        powers[index]=powers[index-1]<<1;//puterile lui 2
        index++;
    }
    floorPowerTwo[1]=0;
    int nextPowerOf2=2;
    for(int i=2; i<=n; i++){//precalculam cea mai mare putere de 2 mai mica decat n
         if(i==nextPowerOf2){//la putere de 2
            floorPowerTwo[i]=floorPowerTwo[i-1]+1;
            nextPowerOf2<<=1;//actualizam lucrurile
         }
         else{
            floorPowerTwo[i]=floorPowerTwo[i-1];//sau altfel, pastram asa cum e
         }
    }
    //construim matricea interv cu minime de intervale
    for(int j=0; j<index; j++){//pentru fiecare lungime putere de 2
        for(int i=0; i<n; i++){//si pt fiecare intrare
            if(j==0){//daca e prima coloana
                interv[i][j]=a[i];//e un element, il trec uite-asa
            }
            else{//altfel
                interv[i][j]=min(interv[i][j-1], interv[i+powers[j-1]][j-1]);//fac recurenta pe cele 2 subintervale aferente
            }
        }
    }
    for(int i=0; i<m; i++){
        cin>>lo>>hi;
        --lo, --hi;
        int gap=hi-lo+1;//astuia ii calculam puterea lui 2 cae acopera tot intervalul- cu suprapuneri
        cout<<min(interv[lo][floorPowerTwo[gap]], interv[hi-powers[floorPowerTwo[gap]]+1][floorPowerTwo[gap]])<<"\n";
        //scriem minimul dintre cele 2 intervale ce acopera intreg intervalul de query
    }
    return 0;
}