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

:heavy_check_mark: Fenwic-Tree (Binary-Indexed-Tree)
(Data-Structure/Range-Accumulate/FenwicTree.hpp)

Verified with

Code

#pragma once
#include <vector>
#include <cassert>

/**
 * @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 2 "Data-Structure/Range-Accumulate/FenwicTree.hpp"
#include <vector>
#include <cassert>

/**
 * @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;
    }
};
Back to top page