Cod sursa(job #2750690)

Utilizator icnsrNicula Ionut icnsr Data 12 mai 2021 19:56:33
Problema Range minimum query Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.59 kb
#include <cstdio>
#include <vector>
#include <climits>
#include <iostream>

struct Min
{
        constexpr int operator()(const int a, const int b) const
        {
                return std::min(a, b);
        }
};

template<typename Pred>
class IntTree
{
public:
        IntTree(std::vector<int>& vec)
            : n(vec.size())
        {
                data.resize(12 * n, 0);

                for(unsigned i = 0; i < n; ++i)
                {
                        insert(i + 1, i + 1, vec[i]);
                }
        }

        void insert(const unsigned l, const unsigned r, const int value)
        {
                insert(1, 1, n, l, r, value);
        }

        int query(const unsigned l, const unsigned r)
        {
                return query(1, 1, n, l, r);
        }

        static unsigned lchild(const unsigned index)
        {
                return index * 2;
        }

        static unsigned rchild(const unsigned index)
        {
                return index * 2 + 1;
        }

        static constexpr int DUMMY = INT_MAX;

private:
        void insert(const unsigned index, const unsigned left, const unsigned right,
                    const unsigned l, const unsigned r, const int value)
        {
                if(l > right || r < left)
                {
                        return;
                }
                if(left == right)
                {
                        data[index] = value;
                        return;
                }

                const unsigned mij = left + (right - left) / 2;
                const unsigned lc_idx = lchild(index);
                const unsigned rc_idx = rchild(index);

                if(l <= mij)
                {
                        insert(lc_idx, left, mij, l, std::min(mij, r), value);
                }
                if(r > mij)
                {
                        insert(rc_idx, mij + 1, right, std::max(mij + 1, l), r, value);
                }

                data[index] = Pred{}(data[lc_idx], data[rc_idx]);
        }

        int query(const unsigned index, const unsigned left, const unsigned right,
                  const unsigned l, const unsigned r)
        {
                if(l > right || r < left)
                {
                        return DUMMY;
                }
                if(l == left && r == right)
                {
                        return data[index];
                }

                const unsigned mij = left + (right - left) / 2;
                const unsigned lc_idx = lchild(index);
                const unsigned rc_idx = rchild(index);

                int a = DUMMY;
                int b = DUMMY;
                if(l <= mij)
                {
                        a = query(lc_idx, left, mij, l, std::min(mij, r));
                }
                if(r > mij)
                {
                        b = query(rc_idx, mij + 1, right, std::max(mij + 1, l), r);
                }
                return std::min(a, b);
        }

private:
        std::vector<int> data;
        unsigned n;
};

int main()
{
        std::freopen("rmq.in", "r", stdin);
        std::freopen("rmq.out", "w", stdout);

        unsigned N, M;
        std::scanf("%u%u", &N, &M);

        std::vector<int> vec;
        vec.reserve(N);
        for(unsigned i = 0; i < N; ++i)
        {
                int value;
                std::scanf("%d", &value);

                vec.push_back(value);
        }

        IntTree<Min> itree(vec);
        for(unsigned i = 0; i < M; ++i)
        {
                int a, b;
                std::scanf("%d%d", &a, &b);

                std::printf("%d\n", itree.query(a, b));
        }
}