Cod sursa(job #2244522)

Utilizator cosmin.pascaruPascaru Cosmin cosmin.pascaru Data 22 septembrie 2018 22:56:28
Problema Range minimum query Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.32 kb
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <assert.h>
#include <queue>
#include <chrono>
#include <memory>

using LL = long long;
using ULL = int long long;

const std::string _problemName = "rmq";

namespace std {
std::ifstream fin(_problemName + ".in");
std::ofstream fout(_problemName + ".out");
}

 #define USE_FILES

#ifdef USE_FILES
#define cin fin
#define cout fout
#endif

struct RMQ {

public:

    RMQ(std::vector<int>&& v) {
        rmq_.emplace_back(std::move(v));
        build();
    }

    int query(int left, int right) {
        int intervalSize = right - left;
        int rowIdx = computeQueryRowIdx(intervalSize);

        // element on [row][col] = min(v[col], ..., v[col + (1 << row) - 1])

        int leftMin  = rmq_[rowIdx][ left                  ];
        int rightMin = rmq_[rowIdx][ right - (1 << rowIdx) ];

        return std::min(leftMin, rightMin);
    }

private:

    int computeQueryRowIdx(int intervalSize) {
        int idx = 0;
        while ((1 << idx) <= intervalSize) {
            ++idx;
        }
        return idx - 1;
    }

    void build() {
        int size = rmq_[0].size();

        for (int row = 1; (1 << row) <= size; ++row) {
            int rowSize = computeRowSize(size, row);
            rmq_.emplace_back(rowSize);

            for (int col = 0; col < rowSize; ++col) {
                updateCell(row, col);
            }
        }
    }

    void updateCell(int row, int col) {
        int left  = leftChild(row, col);
        int right = rightChild(row, col); 
        rmq_[row][col] = std::min(left, right);
    }

    int leftChild(int row, int col) {
        return rmq_[row - 1][col];
    }
    int rightChild(int row, int col) {
        return rmq_[row - 1][col + (1 << (row - 1))];
    }

    int computeRowSize(int topSize, int rowIdx) {
        return topSize - (1 << rowIdx) + 1;
    }

    std::vector<std::vector<int>> rmq_;
};

int main() {

    int n, m;
    std::cin >> n >> m;

    std::vector<int> arr(n);

    for (int idx = 0; idx < n; ++idx) {
        std::cin >> arr[idx];
    }

    RMQ rmq(std::move(arr));

    while (m--) {
        int x, y;
        std::cin >> x >> y;
        x--, y--;

        std::cout << rmq.query(x, y + 1) << '\n';
    }

    return 0;
}