Cod sursa(job #2619061)

Utilizator ReksioCroftOctavian Florin Staicu ReksioCroft Data 26 mai 2020 20:41:58
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.02 kb
#include <cstdio>
#include "cstdlib"
#include <cmath>
#include <algorithm>
#include <cassert>


const int nMax = 100000;
const int logMax = ( int ) log2( nMax ) + 1;
int v[logMax][nMax]; ///v[i][j] = min pe intervalul [i...i+2^j)


class bitSemnificativ {
    int *pozBitSemnificativ = ( int * ) calloc( 256, 4 );
public:
    bitSemnificativ() {
        int co = 1;
        for ( int i = 2; i < 256; i <<= 1 ) {
            for ( int j = 0; j < i; j++ ) {
                pozBitSemnificativ[ i + j ] = co;
            }
            co++;
        }
    }


    int getPozBitSemnificativ( int nr ) {
        int co = 0;
        while ( nr >> 8 ) {
            co += 8;
            nr >>= 8;
        }
        return co + pozBitSemnificativ[ nr ];
    };

    bitSemnificativ( const bitSemnificativ &dummy ) = delete;

    bitSemnificativ &operator=( const bitSemnificativ &dummy ) = delete;


    ~bitSemnificativ() {
        delete[] pozBitSemnificativ;
    }
} ob;


void rmq( int n ) {
    for ( int i = 1; i <= ob.getPozBitSemnificativ( n ); i++ ) {
        for ( int j = 0; j < n - 1; j++ ) {
            v[ i ][ j ] = std::min( v[ i - 1 ][ j ], v[ i - 1 ][ std::min( n - 1, j + ( 1 << ( i - 1 ) ) ) ] );
        }
        v[ i ][ n - 1 ] = v[ i - 1 ][ n - 1 ];
    }
}


int main() {
    int n, m;
    FILE *fin, *fout;
    fin = fopen( "rmq.in", "r" );
    fout = fopen( "rmq.out", "w" );
    assert( fscanf( fin, "%d%d", &n, &m ) == 2 );
    for ( int i = 0; i < n; i++ ) {
        assert( fscanf( fin, "%d", &v[ 0 ][ i ] ) == 1 );
    }

    rmq( n );
    for ( int i = 0; i < m; i++ ) {
        int a, b;
        assert( fscanf( fin, "%d%d", &a, &b ) == 2 );
        a--;
        b--;
        int diff = b - a + 1;
        int nr = ob.getPozBitSemnificativ( diff );
        if ( 1 << nr == diff )
            fprintf( fout, "%d\n", v[ nr ][ a ] );
        else {
            int mini = std::min( v[ nr ][ a ], v[ nr ][ b - ( 1 << nr ) + 1 ] );
            fprintf( fout, "%d\n", mini );
        }
    }
    fclose( fin );
    fclose( fout );
    return 0;
}