Cod sursa(job #2763731)

Utilizator borcanirobertBorcani Robert borcanirobert Data 16 iulie 2021 14:32:13
Problema Range minimum query Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.41 kb
// https://www.infoarena.ro/problema/rmq

#include <iostream>
#include <vector>
#include <fstream>

/// This is a template for range minimum query data structure
template<class T>
class RMQ{
public:
    /// Creates a new RMQ with given array
    /// Parameters:
    ///     a: a vector of elements of type T, which will be used to compute RMQ
    RMQ(const std::vector<T>& a)
    {
        N = static_cast<int>(a.size());
        log2_size = 0;
        while ((1 <<log2_size) < N + 1)
            ++log2_size;
        computeLog2Values();

        rmq = std::vector<std::vector<T>>(log2_size, std::vector<T>(a.size()));
        for (size_t i = 0; i < a.size(); ++i)
            rmq[0][i] = a[i];
        computeRMQ();
    }

    /// Query to find the minimum value from given interval
    /// Parameters:
    ///     x: the start of the interval
    ///     y: the end of the interval
    /// Return value: The minimum in interval [x, y]
    T query(int x, int y)
    {
        int lg = log2_values[y - x + 1];
        int p2 = y - (1 << lg) + 1;

        return std::min(rmq[lg][x], rmq[lg][p2]);
    }

private:
    void computeLog2Values()
    {
        log2_values = std::vector<int>(N + 1);
        log2_values[1] = 0;
        for (size_t i = 2; i < log2_values.size(); ++i)
        {
            log2_values[i] = log2_values[i - 1];
            if ((1 << (log2_values[i] + 1)) <= i)
                ++log2_values[i];
        }
    }

    void computeRMQ()
    {
        for (int k = 1; k < log2_size; ++k)
            for (int i = 0; i < N; ++i)
            {
                int p2 = std::min(N - (1 << (k - 1)), i + (1 << (k - 1)));
                rmq[k][i] = std::min(rmq[k - 1][i], rmq[k - 1][p2]);
            }
    }

    std::vector<std::vector<T>> rmq;
    std::vector<int> log2_values;
    int log2_size;
    int N;
};

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

int N, M;
std::vector<int> a;

void ReadData();
void AnswerQueries();

int main()
{
    ReadData();
    AnswerQueries();    

    fin.close();
    fout.close();
    return 0;
}

void ReadData()
{
    fin >> N >> M;

    a = std::vector<int>(N);
    for (int i = 0; i < N; ++i)
        fin >> a[i];
}

void AnswerQueries()
{
    RMQ<int> rmq{a};

    int x, y;
    while (M--)
    {
        fin >> x >> y;
        fout << rmq.query(x - 1, y - 1) << '\n';
    }
}