67# ifndef TPL_FENWICK_TREE_H
68# define TPL_FENWICK_TREE_H
73# include <initializer_list>
74# include <type_traits>
90 std::is_arithmetic_v<T> &&
91 std::totally_ordered<T> &&
92 std::is_signed_v<T> &&
93 !std::same_as<T, bool>;
102 template <
typename F,
typename T>
104 requires(
const F& f,
const T& a,
const T& b)
106 { f(a, b) } -> std::convertible_to<T>;
139 template <
typename T,
157 static constexpr size_t lowbit(
size_t x)
noexcept
166 for (
size_t i = 1; i <= n; ++i)
167 if (
const size_t parent = i + lowbit(i); parent <= n)
168 tree(parent) = plus_op(tree(parent), tree(i));
175 for (
size_t i = 0; i < n; ++i)
181 template <
class StdIt>
185 for (; first != last; ++first)
191 template <
class AlephIt>
195 for (; it.has_curr(); it.next_ne())
196 tree(i++) = it.get_curr();
213 : tree(num + 1,
T()), n(num),
214 plus_op(pop), minus_op(
mop)
230 plus_op(pop), minus_op(
mop)
243 : tree(values.
size() + 1,
T()), n(values.
size()),
244 plus_op(pop), minus_op(
mop)
246 fill_from_indexed([&values](
size_t i) {
return values(i); });
260 : tree(values.
size() + 1,
T()), n(values.
size()),
261 plus_op(pop), minus_op(
mop)
263 fill_from_indexed([&values](
size_t i) {
return values[i]; });
274 : tree(values.
size() + 1,
T()), n(values.
size()),
275 plus_op(pop), minus_op(
mop)
277 fill_from_aleph_it(values.
get_it());
297 <<
"Gen_Fenwick_Tree::update: index " << i <<
" >= size " << n;
299 for (++i; i <= n; i += i & (-i))
300 tree(i) = plus_op(tree(i), delta);
312 <<
"Gen_Fenwick_Tree::prefix: index " << i <<
" >= size " << n;
315 for (++i; i > 0; i -= i & (-i))
316 s = plus_op(s, tree(i));
330 <<
"Gen_Fenwick_Tree::query: r=" << r <<
" >= n=" << n;
332 <<
"Gen_Fenwick_Tree::query: l=" <<
l <<
" > r=" << r;
357 void set(
const size_t i,
const T & value)
359 update(i, minus_op(value, get(i)));
375 for (
size_t i = 0; i < n; ++i)
384 std::swap(n,
other.n);
385 std::swap(plus_op,
other.plus_op);
386 std::swap(minus_op,
other.minus_op);
410 template <FenwickArithmetic T>
434 const size_t nn = this->
n;
452 return pos <
nn ? pos :
nn;
496 template <FenwickArithmetic T>
506 return static_cast<T>(i + 1) *
b1.prefix(i) -
b2.prefix(i);
514 for (
size_t i = 1; i <
n; ++i)
515 d2(i) = d(i) *
static_cast<T>(i);
528 :
b1(num),
b2(num),
n(num)
551 for (
size_t i = 1; i <
n; ++i, ++it)
571 for (
size_t i = 1; i <
n; ++i)
595 <<
"Range_Fenwick_Tree::update: l=" <<
l <<
" > r=" << r;
597 <<
"Range_Fenwick_Tree::update: r=" << r <<
" >= size " <<
n;
600 b2.update(
l, delta *
static_cast<T>(
l));
605 b1.update(r + 1,
neg);
606 b2.update(r + 1,
neg *
static_cast<T>(r + 1));
628 <<
"Range_Fenwick_Tree::prefix: index " << i <<
" >= size " <<
n;
643 <<
"Range_Fenwick_Tree::query: r=" << r <<
" >= n=" <<
n;
645 <<
"Range_Fenwick_Tree::query: l=" <<
l <<
" > r=" << r;
663 void set(
const size_t i,
const T & value)
681 for (
size_t i = 0; i <
n; ++i)
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Standard functor implementations and comparison objects.
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
void swap(Array &s) noexcept
Swap this with s
Dynamic singly linked list with functional programming support.
Fenwick tree over an arbitrary abelian group.
void fill_from_std_iter(StdIt first, StdIt last)
Fill the internal storage from a standard iterator range and build.
Array< T > values() const
Reconstruct all original values into an Array.
T query(const size_t l, const size_t r) const
Range query: Plus(a[l], a[l+1], ..., a[r]).
constexpr bool is_empty() const noexcept
True if the tree contains no elements.
Gen_Fenwick_Tree(const DynList< T > &values, Plus pop=Plus(), Minus mop=Minus())
Construct from a DynList<T> in O(n) time.
void set(const size_t i, const T &value)
Set a[i] = value.
void fill_from_aleph_it(AlephIt it)
Fill the internal storage from an Aleph-style iterator (get_it()) and build.
void swap(Gen_Fenwick_Tree &other) noexcept
Swap this tree with other in O(1).
T prefix(size_t i) const
Prefix query: Plus(a[0], a[1], ..., a[i]).
T get(const size_t i) const
Retrieve the logical value a[i].
void build()
O(n) bottom-up construction of the tree array from raw values already placed in tree[1....
Gen_Fenwick_Tree(const Gen_Fenwick_Tree &)=default
Gen_Fenwick_Tree(const size_t num, Plus pop=Plus(), Minus mop=Minus())
Construct a tree with num elements, all equal to the identity T().
static constexpr size_t lowbit(size_t x) noexcept
Return the least significant set bit of x (as a mask).
void fill_from_indexed(F getter)
Fill the internal storage from a 0-based indexed getter and build.
T Item_Type
The type of element stored in the tree.
Gen_Fenwick_Tree(Gen_Fenwick_Tree &&) noexcept=default
Gen_Fenwick_Tree(const Array< T > &values, Plus pop=Plus(), Minus mop=Minus())
Construct from an Array<T> in O(n) time.
Gen_Fenwick_Tree(std::initializer_list< T > il, Plus pop=Plus(), Minus mop=Minus())
Construct from an initializer list in O(n) time.
Gen_Fenwick_Tree(const std::vector< T > &values, Plus pop=Plus(), Minus mop=Minus())
Construct from a std::vector<T> in O(n) time.
constexpr size_t size() const noexcept
Number of logical elements.
Fenwick tree supporting range updates and range queries.
void build_from_diffs(const Array< T > &d)
Rebuild b1 and b2 from a difference array stored in d.
void point_update(const size_t i, const T &delta)
Point update: add delta to a[i].
Range_Fenwick_Tree(const size_t num)
Construct a tree with num elements, all zero.
void update(size_t l, const size_t r, const T &delta)
Range update: add delta to every a[i] with l <= i <= r.
constexpr bool is_empty() const noexcept
True if the tree contains no elements.
Range_Fenwick_Tree(Range_Fenwick_Tree &&) noexcept=default
void swap(Range_Fenwick_Tree &other) noexcept
Swap this tree with other in O(1).
T get(const size_t i) const
Retrieve the logical value a[i].
void set(const size_t i, const T &value)
Set a[i] = value.
Range_Fenwick_Tree(const Array< T > &values)
Construct from an Array<T> in O(n) time.
Range_Fenwick_Tree(std::initializer_list< T > il)
Construct from an initializer list in O(n) time.
Range_Fenwick_Tree(const Range_Fenwick_Tree &)=default
Array< T > values() const
Reconstruct all original values into an Array.
T prefix(const size_t i) const
Prefix query: sum of a[0..i].
constexpr size_t size() const noexcept
Number of logical elements.
T query(const size_t l, const size_t r) const
Range query: sum of a[l..r].
T prefix_sum(size_t i) const
Internal: prefix sum P(i) = (i+1)*B1.prefix(i) - B2.prefix(i)
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
Arithmetic domain accepted by Fenwick specializations.
Binary operation compatible with Fenwick tree group functors.
Main namespace for Aleph-w library functions.
size_t size(Node *root) noexcept
std::decay_t< typename HeadC::Item_Type > T
static void prefix(Node *root, DynList< Node * > &acc)
void next()
Advance all underlying iterators (bounds-checked).
DynList< T > maps(const C &c, Op op)
Classic map operation.
Fenwick tree for arithmetic types with find_kth support.
size_t find_kth(T k) const
Find the smallest 0-based index i such that prefix(i) >= k.
Dynamic array container with automatic resizing.
Alias for htlist.H (DynList implementation).