Cod sursa(job #2657140)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 9 octombrie 2020 19:17:07
Problema Range minimum query Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.21 kb
#include <bits/stdc++.h>

std::ifstream input ("rmq.in");
std::ofstream output("rmq.out");

#define num_type    int
#define MIDDLE      (left+right)/2

#define MAXPOWN 1048576
#define MAXLEV  21

int N, M, P;
std::vector <num_type> V;

class DisjointSparseTable {
public:
    DisjointSparseTable(std::vector <num_type> &V) : V(V) {
        int n = V.size();
        size = n;
        maxLevel = __builtin_clz(n) ^ 31;		// floor(log2(N))
        if ((1<<maxLevel) != n)
            size = 1 << ++ maxLevel;

        table.resize(MAXLEV);
        for (auto &it:table)
            it.resize(MAXPOWN, 0);

        build(0, 0, size);
    }

    void build(int level, int left, int right) {
        table[level][MIDDLE] = func(V[MIDDLE]);
        for (int i=MIDDLE-1; i>=left; i--)
            table[level][i] = func(table[level][i+1], V[i]);

        if (MIDDLE+1 < right) {
            table[level][MIDDLE+1] = func(V[MIDDLE+1]);
            for (int i=MIDDLE+2; i<right; i++)
                table[level][i] =  func(table[level][i-1], V[i]);
        }

        if (left + 1 != right) {
            build(level+1, left, MIDDLE);
            build(level+1, MIDDLE, right);
        }
    }

    int query(int left, int right) {
        if (left == right)
            return func(V[left]);
        int k2 = __builtin_clz(left^right) ^ 31;

        int lvl = maxLevel - 1 - k2;

        num_type ans = table[lvl][left];
        if (right & ((1<<k2) - 1))
            ans = func(ans, table[lvl][right]);
        return ans;
    }

private:
    num_type func (const num_type &num, const num_type &other) {
        return std::min(num, other);
    }
    num_type func (const num_type &num) {
        return num;
    }

    std::vector <num_type> V;
    std::vector <std::vector <num_type>> table;
    int maxLevel, size;
};

int main()
{
    std::cin.tie(NULL);
    std::cout.tie(NULL);
    std::ios_base::sync_with_stdio(false);

    input >> N >> M;
    V.resize(N);
    for (auto &it:V) input >> it;

    DisjointSparseTable table(V);

    for (int i=0, x, y; i<M; ++i) {
        input >> x >> y;
        --x, --y;
        output << table.query(x, y) << '\n';
    }

    return 0;
}