Fenwick tree
(Mylib/DataStructure/FenwickTree/fenwick_tree.cpp)
- View this file on GitHub
- Last update: 2021-04-23 23:44:44+09:00
- Link:
View error logs on GitHub Actions
Operations
可換群$(G, +, e)$上の列を扱う。
FenwickTree(n)
-
update(i, v)
- $a_i \leftarrow a_i + v$に更新する。
- Time complexity $O(\log n)$
-
get(i)
- $a_0 + a_1 + \ldots + a_{i-1}$を返す。
- Time complexity $O(\log n)$
-
get(l, r)
- $a_l + a_{l+1} + \ldots + a_{r-1}$を返す。
- Time complexity $O(\log n)$
-
at(i)
- $a_i$を返す。
- Time complexity $O(\log n)$
Requirements
-
AbelianGroup
は可換性・結合性を満たす演算op
と単位元id
と逆元を与える関数inv
をもつ。
Notes
Problems
References
Required by
Verified with
test/aoj/DSL_2_B/main.fenwick_tree.test.cpp
test/yosupo-judge/rectangle_sum/main.fenwick_tree.test.cpp
Code
#pragma once
#include <cassert>
#include <vector>
namespace haar_lib {
template <typename AbelianGroup>
class fenwick_tree {
public:
using value_type = typename AbelianGroup::value_type;
private:
AbelianGroup G_;
int size_;
std::vector<value_type> data_;
public:
fenwick_tree() {}
fenwick_tree(int size) : size_(size), data_(size + 1, G_()) {}
void update(int i, const value_type &val) {
assert(0 <= i and i < size_);
i += 1; // 1-index
while (i <= size_) {
data_[i] = G_(data_[i], val);
i += i & (-i);
}
}
value_type fold(int i) const { // [0, i)
assert(0 <= i and i <= size_);
value_type ret = G_();
while (i > 0) {
ret = G_(ret, data_[i]);
i -= i & (-i);
}
return ret;
}
value_type fold(int l, int r) const { // [l, r)
assert(0 <= l and l <= r and r <= size_);
return G_(fold(r), G_.inv(fold(l)));
}
value_type operator[](int x) const {
return fold(x, x + 1);
}
};
} // namespace haar_lib
#line 2 "Mylib/DataStructure/FenwickTree/fenwick_tree.cpp"
#include <cassert>
#include <vector>
namespace haar_lib {
template <typename AbelianGroup>
class fenwick_tree {
public:
using value_type = typename AbelianGroup::value_type;
private:
AbelianGroup G_;
int size_;
std::vector<value_type> data_;
public:
fenwick_tree() {}
fenwick_tree(int size) : size_(size), data_(size + 1, G_()) {}
void update(int i, const value_type &val) {
assert(0 <= i and i < size_);
i += 1; // 1-index
while (i <= size_) {
data_[i] = G_(data_[i], val);
i += i & (-i);
}
}
value_type fold(int i) const { // [0, i)
assert(0 <= i and i <= size_);
value_type ret = G_();
while (i > 0) {
ret = G_(ret, data_[i]);
i -= i & (-i);
}
return ret;
}
value_type fold(int l, int r) const { // [l, r)
assert(0 <= l and l <= r and r <= size_);
return G_(fold(r), G_.inv(fold(l)));
}
value_type operator[](int x) const {
return fold(x, x + 1);
}
};
} // namespace haar_lib