Cod sursa(job #2496285)

Utilizator NineshadowCarapcea Antonio Nineshadow Data 20 noiembrie 2019 17:13:09
Problema Range minimum query Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.74 kb
#include <bits/stdc++.h>

using namespace std;
ifstream in("rmq.in");
ofstream out("rmq.out");

#define MAX_ELEM 0xfffffff
void preprocess(const std::vector<int> input, std::vector<int>& block) {
    int s = block.size(), n = input.size();
    for(int k = 0, i = 0; k < s; ++k) {
        int cur_min = MAX_ELEM;
        for(int t = 0; t < s && i < n; ++t, ++i) {
            if(input[i] < cur_min) {
                cur_min = input[i];
                block[k] = cur_min;
            }
        }
        
    }
}


std::vector<int> rmq(const std::vector<int>& input, const std::vector< std::pair<int, int> >& queries) {
    int n = input.size(); // input size 
    int block_size = (int) sqrt(n + .0) + 1; // block size
    //std::cout << "block size: " << block_size << " blockCount: " << block_count << "\n";
    std::vector<int> ans; // return vector
    ans.reserve(queries.size());
    std::vector<int> block(block_size); // block vector
    preprocess(input, block);

    for(std::pair<int, int> q : queries) {
        int l = q.first - 1, r = q.second - 1;
        //std::cout << l << " " << r << ": ";
        int block_l = l / block_size, block_r = r / block_size;
        //std::cout << block_l << " " << block_r << ": ";
        int cur_min = MAX_ELEM;

        // If left and right are in the same block
        if(block_l == block_r) {
            for(int i = l; i <= r; ++i) {
                if(input[i] < cur_min) {
                    cur_min = input[i];
                }
            }
        } else {        
            // Go through what's left of the left block
            for(int i = l, end_left = (block_l+1)*block_size; i < end_left; ++i) {
                if(input[i] < cur_min) {
                    cur_min = input[i];
                }
            }
            // Go through inner blocks
            for(int i = block_l + 1; i < block_r; ++i) {
                if(block[i] < cur_min) {
                    cur_min = block[i];
                }
            }
            // Go through what's left of the right block
            for(int i = block_r * block_size; i <= r; ++i) {
                if(input[i] < cur_min) {
                    cur_min = input[i];
                }
            }
        }
        //std::cout << cur_min << "\n";
        ans.push_back(cur_min);
    }

    return ans;
}

int main() {
    int n, q;
    in >> n >> q;
    vector<int> input;
    input.reserve(n);
    vector<pair<int, int>> queries;
    queries.reserve(q);
    for(int i = 0; i < n; ++i) {
        int t;
        in >> t;
        input.push_back(t);
    }

    for(int i = 0; i < q; ++i) {
        int l, r;
        in >> l >> r;
        queries.push_back(make_pair(l,r));
    }

    vector<int> ans = rmq(input, queries);

    for(int i : ans) {
        cout << i << "\n";
    }
}