Cod sursa(job #2700868)

Utilizator MenelausSontea Vladimir Menelaus Data 29 ianuarie 2021 09:47:52
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.45 kb
#include <iostream>
#include <fstream>
#include <cmath>

const int N=100001;

std::ifstream in("rmq.in");
std::ofstream out("rmq.out");

/// l[i][j] este indicele minimului elementelor din intervalul care incepe in i si are o lungime de 2^j
int v[N], l[N][20];

int log2(int n)
{
    int j=0;
    while((1<<j)<=n)
    {
        j++;
    }
    return j-1;
}

void preprocess(int n)
{
    for(int i=1; i<=n; i++)
    {
        l[i][0]=i;
    }

    int log_n=log2(n);

    for(int j=1; j<=log_n; j++)
    {

        int j2=(int)std::pow(2, j);
        int jminus1_2=(int)std::pow(2, j-1);

        for(int i=1; i+j2-1<=n; i++)
        {
            /// l[i][j-1] este minimul de pe i pe i+2^(j-1)-1
            /// l[i+jminus1_2][j-1] este minimul de pe i+2^(j-1) pe i+2^j-1

            if( v[l[i][j-1]] <= v[l[i+jminus1_2][j-1]] )
            {
                l[i][j]=l[i][j-1];
            }

            else
            {
                l[i][j]=l[i+jminus1_2][j-1];
            }
        }
    }
}

int query(int L, int R)
{
    int apropiat=log2(R-L+1);

    /// comparam (L, L+2^j-1) cu (R-2^j+1, R)

    return std::min(v[l[L][apropiat]], v[l[R-(1<<apropiat)+1][apropiat]]);
}

int main()
{
    int n, m, l, r;
    in>>n>>m;

    for(int i=1; i<=n; i++)
    {
        in>>v[i];
    }

    preprocess(n);

    for(int i=1; i<=m; i++)
    {
        in>>l>>r;
        out<<query(l, r)<<"\n";
    }
}