e6nlaq/library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: include/e6nlaq/imos.hpp

Depends on

Verified with

Code

#include "imos/imos.hpp"
#line 2 "include/e6nlaq/imos/imos.hpp"

#define E6NLAQ_IMOS_IMOS_HPP

#include <stdexcept>
#include <type_traits>
#include <vector>

#line 2 "include/e6nlaq/concepts.hpp"

#define E6NLAQ_CONCEPTS_HPP

namespace e6nlaq {
template <typename T>
concept add_assignable = requires(T a, T b) {
    { a += b };
};

template <typename T>
concept subtract_assignable = requires(T a, T b) {
    { a -= b };
};
}  // namespace e6nlaq
#line 10 "include/e6nlaq/imos/imos.hpp"

namespace e6nlaq {

/**
 * @brief imos法を実装したクラス
 * @tparam T 累積和の型
 */
template <typename T>
    requires add_assignable<T> && subtract_assignable<T>
class imos {
   private:
    std::vector<T> dat;

   public:
    imos() : dat(0) {};

    /**
     * @brief コンストラクタ
     * @param n 配列のサイズ
     * @param init 初期値
     * @param e 単位元
     */
    explicit imos(std::size_t n, const T& init, const T& e) : dat(n + 1, e) {
        add(0, n, init);
    }

    /**
     * @brief コンストラクタ(整数)
     * @param n 配列のサイズ
     * @param init 初期値
     */
    explicit imos(std::size_t n, T init = T(0))
        requires std::is_integral_v<T>
        : imos(n, init, 0) {}

    explicit imos(const std::vector<T>& init)
        requires std::is_integral_v<T>
        : dat(init.size() + 1, 0) {
        for (std::size_t i = 0; i < init.size(); ++i) {
            add(i, i + 1, init[i]);
        }
    }

    explicit imos(const std::vector<T>& init, const T& e) : dat(init.size() + 1, e) {
        for (std::size_t i = 0; i < init.size(); ++i) {
            add(i, i + 1, init[i]);
        }
    }

    /**
     * @brief 区間 [l, r) に x を加える O(1)
     * @param l 区間の左端(含む)
     * @param r 区間の右端(含まない)
     * @param x 加算する値
     * @throw std::out_of_range l > r または r > dat.size() の場合
     */
    void add(std::size_t l, std::size_t r, T x) {
        if (l > r || r > dat.size()) {
            throw std::out_of_range("imos::add: invalid range");
        }
        dat[l] += x;
        dat[r] -= x;
    }

    /**
     * @brief 累積和を計算して返す O(N)
     * @return 累積和の配列
     */
    std::vector<T> get() const {
        std::vector<T> res(dat.size() - 1);
        res[0] = dat[0];
        for (std::size_t i = 1; i < res.size(); i++)
            res[i] = res[i - 1] + dat[i];

        return res;
    }
};

}  // namespace e6nlaq
#line 2 "include/e6nlaq/imos.hpp"
Back to top page