Cod sursa(job #2069651)

Utilizator Andreiii500Andrei Puiu Andreiii500 Data 18 noiembrie 2017 17:38:50
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.3 kb
#include<iostream>
#include<fstream>
#include<cassert>
#include<cmath>
using namespace std;

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

const int N = 100000;
const int NLOG = 17 + 1; /// +1 Because we want to include level 0 too!

void array_to_RMQ_matrix(int v[], int n, int rmq[][N], int MAX_LEVEL){ /// Creates min() RMQ table "rmq" from Array "v"
    /// Compute RMQ level 0
    for(int i=0; i<n; ++i)
        rmq[0][i] = v[i];

    //for(int index = 0; index < n; ++index) cout<<rmq[0][index]<<" "; cout<<"\n";

    /// Compute RMQ levels 1 to MAX_LEVEL
    for(int level = 1; level <= 17; ++level)
    {
        int sequence_length = 1 << level;
        int last_sequence_index = n - sequence_length + 1;

        for(int index = 0; index < last_sequence_index; ++index)
            rmq[level][index] = min(rmq[level-1][index], rmq[level-1][index + sequence_length / 2]);

        //for(int index = 0; index < last_sequence_index; ++index) cout<<rmq[level][index]<<" "; cout<<"\n";
    }
}

int MSD(int x){ /// Base 2 MSD of number X
    while(x & (x-1)) /// X isn't a power of 2 yet
        x &= x-1; /// Remove X's LSD

    return x;
}

int queryRMQ(int rmq[][N], int n, int a, int b){ /// Queries the RMQ table in interval [a, b]
    int query_interval_length = b-a+1;
    int sequence_length = MSD(query_interval_length); /// The maximal RMQ sequence length we can query
    int level = log2(sequence_length);
    int offset = query_interval_length - sequence_length;

    return min(rmq[level][a], rmq[level][a + offset]); /// min <- [a, a + 2^level] U [a+offset, b]
}

int main()
{
    /// Local Variables
    int rmqArray[NLOG][N]; /// rmqArray[level][index] = min(index, index+1, ..., index + 2^level);
    int values[N];
    int n,q;

    /// Unit Testing :D
    assert(MSD(16) == 16); /// 10000
    assert(MSD(9) == 8);   /// 01001
    assert(MSD(7) == 4);   /// 00111

    /// Input
    in>>n>>q;
    for(int i=0; i<n; ++i)
        in>>values[i];

    /// Compute RMQ table
    array_to_RMQ_matrix(values, n, rmqArray, NLOG);

    /// Answer the queries
    for(int i=0; i<q; ++i)
    {
        int leftBound, rightBound;
        in>>leftBound>>rightBound;
        out<<queryRMQ(rmqArray, n, leftBound-1, rightBound-1)<<"\n";
    }


    return 0;
}