Cod sursa(job #2227386)

Utilizator AlexnolifeAlexandru Ica Alexnolife Data 31 iulie 2018 17:49:02
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.14 kb
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdint>
#include <cstddef>
#include <string>
#include <array>
#include <vector>
#include <list>
#include <algorithm>
#include <utility>
#include <type_traits>
#include <limits>
#include <cmath>

std::ifstream f{ "rmq.in" };
std::ofstream g{ "rmq.out" };

constexpr int NMAX = 100000;

int array_size{};
int query_count{};

using matrix_t = std::vector<std::vector<int>>;

std::vector<int> numbers(NMAX);
//std::vector<int> seg_tree(NMAX * 4, std::numeric_limits<int>::max());
/*
void build_seg_tree(int pos, int start, int end)
{
    if(start == end) {
        seg_tree[pos] = numbers[start];
        return;
    }

    int mid = start + (end - start) / 2;

    build_seg_tree(2 * pos + 1, start, mid);
    build_seg_tree(2 * pos + 2, mid + 1, end);

    seg_tree[pos] = std::min(seg_tree[2 * pos + 1], seg_tree[2 * pos + 2]);
}

int get_min_interval(int a, int b, int start, int end, int pos = 0)
{
    if(a <= start && b >= end) {
        return seg_tree[pos];
    }
    if(a > end || b < start) {
        return std::numeric_limits<int>::max();
    }

    int mid = start + (end - start) / 2;

    return std::min(get_min_interval(a, b, start, mid, 2 * pos + 1),
                    get_min_interval(a, b, mid + 1, end, 2 * pos + 2));
}
*/
/*
void update_seg_tree(int node, int start, int end, int pos, int val)
{
    if(start == end) {
        seg_tree[node] = val;
        return;
    }

    int mid = start + (end - start) / 2;

    if(pos <= mid) {
        update_seg_tree(2 * node + 1, start, mid, pos, val);
    }
    else {
        update_seg_tree(2 * node + 2, mid + 1, end, pos, val);
    }

    seg_tree[node] = std::min(seg_tree[2 * pos + 1], seg_tree[2 * pos + 2]);
}
*/
void preprocess(matrix_t& sparse)
{
    const auto& input = numbers;

    int i{};
    int j{};

    for(i = 0; i < array_size; ++i) {
        sparse[i][0] = i;
    }

    for(j = 1; (1 << j) <= array_size; ++j) {
        for(i = 0; i + (1 << j) - 1 < array_size; ++i) {
            if(input[sparse[i][j - 1]] < input[sparse[i + (1 << (j - 1))][j - 1]]) {
                sparse[i][j] = sparse[i][j - 1];
            }
            else {
                sparse[i][j] = sparse[i + (1 << (j - 1))][j - 1];
            }
        }
    }
}

int get_min_interval(matrix_t& sparse, int left, int right)
{
    const auto& input = numbers;

    int l = right - left + 1; 
    int k = static_cast<int>(std::log2(static_cast<double>(l)));
    
    return std::min(input[sparse[left][k]], input[sparse[left + l - (1 << k)][k]]);
}

void read()
{
    f >> array_size >> query_count;

    int i{};

    for(i = 0; i < array_size; ++i) {
        f >> numbers[i];
    }

    //build_seg_tree(0, 0, array_size - 1);
    matrix_t sparse(NMAX, std::vector<int>(
                static_cast<int>(std::log2(static_cast<double>(NMAX))),
                -1));

    preprocess(sparse);

    for(i = 0; i < query_count; ++i) {
        int left{}; 
        int right{};
        
        f >> left >> right;

        g << get_min_interval(sparse, left - 1, right - 1) << '\n';
    }
}
/*
void solve()
{
}
*/
int main(const int, const char *[])
{
    read();
    //solve();
    return 0;
}