Link Search Menu Expand Document
あるまかんライブラリ

:heavy_check_mark: test/yosupo/static-range-sum.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/static_range_sum"
#include <bits/stdc++.h>

#include "../../Data-Structure/Range-Accumulate/cumulative-sum.hpp"
#include "../../Data-Structure/Range-Accumulate/foldLR.hpp"
#include "../../Data-Structure/Range-Accumulate/FenwicTree.hpp"

#include "../../Util/IO/println.hpp"
#include "../../Util/IO/read.hpp"
#include "../../Util/int-alias.hpp"
#include "../../Util/all-macro.hpp"

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

    int N, Q;
    std::cin >> N >> Q;

    auto a = read<int>(N);

    CumulativeSum<i64> cum(a);

    FoldLR<i64> fold(all(a), 0, [](i64 x1, i64 x2) { return x1 + x2; });

    FenwicTree<i64> ft(N);
    for (int i = 0; i < N; ++i) {
        ft.add(i, a[i]);
        assert(ft.at(i) == a[i]);
    }

    while (Q--) {
        int l, r;
        std::cin >> l >> r;

        const auto ans1 = cum.sum(l, r);
        const auto ans2 = fold.foldL(r) - fold.foldL(l);
        const auto ans3 = fold.foldR(l) - fold.foldR(r);
        const auto ans4 = ft.sum(l, r);

        assert(ans2 == ans1);
        assert(ans3 == ans1);
        assert(ans4 == ans1);

        println(ans1);
    }

    return 0;
}
#line 1 "test/yosupo/static-range-sum.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/static_range_sum"
#include <bits/stdc++.h>

#line 5 "Data-Structure/Range-Accumulate/cumulative-sum.hpp"

/**
 * @brief CumulativeSum (累積和)
 */
template <class T>
struct CumulativeSum {
    std::valarray<T> data;

    CumulativeSum() = default;

    template <class Container>
    explicit CumulativeSum(const Container& container)
        : CumulativeSum(container.cbegin(), container.cend()) {}

    template <class InputItr>
    CumulativeSum(InputItr begin, InputItr end)
        : data(std::distance(begin, end) + 1) {
        size_t i;
        InputItr itr;
        for (i = 0, itr = begin; itr != end; ++i, ++itr) {
            data[i + 1] = data[i] + *itr;
        }
    }

    //! [0, r)
    const T prefixSum(size_t r) const { return data[r]; }

    //! [l, r)
    const T sum(size_t l, size_t r) const { return prefixSum(r) - prefixSum(l); }
};
#line 3 "Data-Structure/Range-Accumulate/foldLR.hpp"

/**
 * @brief FoldLR
 */
template <class T>
class FoldLR {
    std::vector<T> m_foldL, m_foldR;
    T m_e;

public:
    FoldLR() = default;

    template <class BidirectionalItr, class Op>
    FoldLR(BidirectionalItr begin, BidirectionalItr end, const T& e, Op op)
        : FoldLR(begin, end, e, op, op) {}

    /**
     * foldLeftOp: (T, Elem) -> T
     * foldRightOp: (Elem, T) -> T
     */
    template <class BidirectionalItr, class FoldLeftOp, class FoldRightOp>
    FoldLR(BidirectionalItr begin, BidirectionalItr end, const T& e, FoldLeftOp foldLeftOp, FoldRightOp foldRightOp)
        : m_foldL(std::distance(begin, end) + 1, e)
        , m_foldR(std::distance(begin, end) + 1, e)
        , m_e(e) {
        size_t i;
        BidirectionalItr itr;
        for (i = 0, itr = begin; itr != end; ++i, ++itr) {
            m_foldL[i + 1] = foldLeftOp(m_foldL[i], *itr);
        }
        for (i = m_foldR.size() - 1, itr = std::prev(end); i > 0; --i, --itr) {
            m_foldR[i - 1] = foldRightOp(*itr, m_foldR[i]);
        }
    }

    /**
     * [0, r)
     * ((((e op a[0]) op a[1]) op a[2]) ... op a[r - 1])
     * foldL(0) returns e();
     */
    const T foldL(size_t r) const { return m_foldL[r]; }

    /**
     * [l, N)
     * (a[l] op ... (a[N - 3] op (a[N - 2] op (a[N - 1] op e))))
     * foldR(N) returns e();
     */
    const T foldR(size_t l) const { return m_foldR[l]; }

    const T e() const { return m_e; }
};
#line 4 "Data-Structure/Range-Accumulate/FenwicTree.hpp"

/**
 * @brief Fenwic-Tree (Binary-Indexed-Tree)
 */
template <class T>
class FenwicTree {
    size_t m_size;
    std::vector<T> dat;

public:
    FenwicTree() = default;

    explicit FenwicTree(size_t n)
        : m_size(n)
        , dat(n + 1) {}

    //! i: [0, n)
    void add(size_t i, const T& value) {
        assert(i < m_size);
        ++i;
        while (i <= m_size) dat[i] += value, i += i & -i;
    }

    //! [0, r)
    const T prefixSum(size_t r) const {
        T acc = 0;
        while (r > 0) acc += dat[r], r -= r & -r;
        return acc;
    }

    //! [l, r)
    const T sum(size_t l, size_t r) const { return prefixSum(r) - prefixSum(l); }

    //! i: [0, n)
    const T at(size_t i) const { return prefixSum(i + 1) - prefixSum(i); }

    //! return `i` s.t. prefixSum(i) >= value
    size_t lowerBound(T value) const {
        if (value <= 0) return 0;
        static const auto B = floorPow2(m_size);
        size_t i = 0;
        for (size_t k = B; k > 0; k >>= 1) {
            if (i + k <= m_size && dat[i + k] < value) {
                value -= dat[i + k];
                i += k;
            }
        }
        return i + 1;
    }

private:
    static inline constexpr size_t floorPow2(size_t x) noexcept {
        size_t ret = 1;
        while (ret <= x) ret <<= 1;
        return ret >> 1;
    }
};
#line 7 "test/yosupo/static-range-sum.test.cpp"

#line 4 "Util/IO/println.hpp"

/**
 * @brief println() (可変個の値を空白区切りで出力して改行する)
 */
inline void println() {
    std::cout << '\n';
}
template <class Head, class... Tail>
inline void println(Head&& head, Tail&&... tail) {
    std::cout << head << &" "[!sizeof...(tail)];
    println(std::forward<Tail>(tail)...);
}
#line 4 "Util/IO/read.hpp"

/**
 * @brief read() (n個入力してContainerに格納して返す)
 */
template <class T = int, template <class, class...> class Container = std::vector>
Container<T> read(size_t n) {
    Container<T> ret(n);
    for (auto& e : ret) std::cin >> e;
    return ret;
}
#line 3 "Util/int-alias.hpp"

/**
 * @brief int-alias (整数型のエイリアス)
 */
using i64 = int64_t;
using u64 = uint64_t;
#line 2 "Util/all-macro.hpp"

/**
 * @brief all()マクロ
 */
#define all(x) std::begin(x), std::end(x)
#define rall(x) std::rbegin(x), std::rend(x)
#line 12 "test/yosupo/static-range-sum.test.cpp"

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

    int N, Q;
    std::cin >> N >> Q;

    auto a = read<int>(N);

    CumulativeSum<i64> cum(a);

    FoldLR<i64> fold(all(a), 0, [](i64 x1, i64 x2) { return x1 + x2; });

    FenwicTree<i64> ft(N);
    for (int i = 0; i < N; ++i) {
        ft.add(i, a[i]);
        assert(ft.at(i) == a[i]);
    }

    while (Q--) {
        int l, r;
        std::cin >> l >> r;

        const auto ans1 = cum.sum(l, r);
        const auto ans2 = fold.foldL(r) - fold.foldL(l);
        const auto ans3 = fold.foldR(l) - fold.foldR(r);
        const auto ans4 = ft.sum(l, r);

        assert(ans2 == ans1);
        assert(ans3 == ans1);
        assert(ans4 == ans1);

        println(ans1);
    }

    return 0;
}
Back to top page