Cod sursa(job #2844921)

Utilizator dana24hdDana N dana24hd Data 6 februarie 2022 11:27:42
Problema Range minimum query Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.84 kb
#include <iostream>
#include <fstream>

using namespace std;

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

/**

I. precalculari pe bucati de sqrt(n)

i      1  2  3  4  5  6  7  8  9  10
a[i]   2  4  3 |1  6  7 |
        M[1]=1   M[2]=4   etc
    query pe (x,y) -> portiunile intregi de sqrt(n) + resturile pana la
                                x, y parcurse
                O( N + sqrt(N)*M )

II. matrice precalculata total

m[i][j] = minimul din (a[i], .. a[j])
m[i][j] = min( m[i][j-1], a[i][j] )
    O(N^2)

SPARSE TABLE ALGORITHM (topcoder)

m[i][j] = indicele minimului din secventa care incepe la i si are
    2^j elemente: a[i], a[i+1], ... a[i + 2^j - 1]

    relatia de recurenta: (impartim secv de 2^j in 2 de 2^j-1
m[i][j] = min( m[i][j-1], m[i + 2^j-1][j-1] )

    pentru query-uri de lungimi care nu sunt putere de 2:
        2 intervale de putere a lui 2 <= lungimea secv
        se vor suprapune, dar nu conteaza pentru minim

    se precalculeaza si puterea maxima pt fiecare numar de la 1 la n


*/

int a[100050];
int m[100050][25];
int log[100050];

int main()
{
    int n, mm;
    in>>n>>mm;

    /// valoarea minima
    for( int i=1; i<=n; i++ ){
        in>>a[i];
        m[i][0]=a[i];
    }

    /// PRECALCULARE

    log[1]=0;
    for( int i=2; i<=n; i++ ){
        log[i] = 1 + log[i/2];
    }

    for( int j=1; (1<<j)<=n; j++ ){ /// lungimea
        for( int i=1; i + (1<<j) - 1 <= n; i++ ){ /// pozitia de inceput
            m[i][j] = min( m[i][j-1], m[i + 1<<(j-1) ][j-1] );
        }
    }

    int x, y;
    for( int i=1; i<=mm; i++ ){

        in>>x>>y;

        /// 2^p <= y-x+1, p maxim
        /// p = log2 (y-x+1)

        int p = log[y-x+1];

        int rez = min( m[x][p], m[y - (1<<p)+1][p] );

        out<<rez<<'\n';

    }

    return 0;
}