You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
2.1 KiB
76 lines
2.1 KiB
#pragma once |
|
|
|
#include <functional> |
|
#include <vector> |
|
|
|
template <typename T, typename Op> |
|
class SegmentTree { |
|
public: |
|
SegmentTree(const std::vector<T>& data, Op op, T identity) |
|
: n_(static_cast<int>(data.size())), |
|
op_(std::move(op)), |
|
identity_(identity), |
|
tree_(4 * n_, identity_) { |
|
if (n_ > 0) { |
|
build(data, 0, 0, n_ - 1); |
|
} |
|
} |
|
|
|
T query(int left, int right) const { |
|
return query(0, 0, n_ - 1, left, right); |
|
} |
|
|
|
void update(int index, T value) { |
|
update(0, 0, n_ - 1, index, value); |
|
} |
|
|
|
private: |
|
int n_; |
|
Op op_; |
|
T identity_; |
|
std::vector<T> tree_; |
|
|
|
void build(const std::vector<T>& data, int node, int start, int end) { |
|
if (start == end) { |
|
tree_[node] = data[start]; |
|
return; |
|
} |
|
int mid = start + (end - start) / 2; |
|
build(data, 2 * node + 1, start, mid); |
|
build(data, 2 * node + 2, mid + 1, end); |
|
tree_[node] = op_(tree_[2 * node + 1], tree_[2 * node + 2]); |
|
} |
|
|
|
T query(int node, int start, int end, int left, int right) const { |
|
if (right < start || end < left) { |
|
return identity_; |
|
} |
|
if (left <= start && end <= right) { |
|
return tree_[node]; |
|
} |
|
int mid = start + (end - start) / 2; |
|
return op_( |
|
query(2 * node + 1, start, mid, left, right), |
|
query(2 * node + 2, mid + 1, end, left, right)); |
|
} |
|
|
|
void update(int node, int start, int end, int index, T value) { |
|
if (start == end) { |
|
tree_[node] = value; |
|
return; |
|
} |
|
int mid = start + (end - start) / 2; |
|
if (index <= mid) { |
|
update(2 * node + 1, start, mid, index, value); |
|
} else { |
|
update(2 * node + 2, mid + 1, end, index, value); |
|
} |
|
tree_[node] = op_(tree_[2 * node + 1], tree_[2 * node + 2]); |
|
} |
|
}; |
|
|
|
using SumSegmentTree = SegmentTree<long long, std::plus<long long>>; |
|
|
|
inline SumSegmentTree make_sum_segment_tree(const std::vector<long long>& data) { |
|
return SumSegmentTree(data, std::plus<long long>{}, 0LL); |
|
}
|
|
|