|
1 | 1 | #ifndef WEILYCODER_STATIC_RANGE_SUM_HPP |
2 | 2 | #define WEILYCODER_STATIC_RANGE_SUM_HPP |
3 | 3 |
|
| 4 | +#include "group.hpp" |
4 | 5 | #include <cstddef> |
| 6 | +#include <stdexcept> |
5 | 7 | #include <vector> |
6 | 8 |
|
7 | 9 | namespace weilycoder { |
8 | | -template <typename T, typename ptr_t = size_t> struct StaticRangeSum { |
| 10 | +template <typename Group> struct StaticRangeSum { |
| 11 | + using value_type = typename Group::value_type; |
| 12 | + using T = value_type; |
| 13 | + |
| 14 | +private: |
9 | 15 | std::vector<T> prefix_sum; |
10 | 16 |
|
11 | | - StaticRangeSum(const std::vector<T> &data) : prefix_sum(data.size() + 1) { |
12 | | - for (ptr_t i = 1; i <= data.size(); ++i) |
13 | | - prefix_sum[i] = prefix_sum[i - 1] + data[i - 1]; |
| 17 | +public: |
| 18 | + explicit StaticRangeSum(const std::vector<T> &data) |
| 19 | + : prefix_sum(data.size() + 1, Group::identity()) { |
| 20 | + for (size_t i = 1; i <= data.size(); ++i) |
| 21 | + prefix_sum[i] = Group::operation(prefix_sum[i - 1], data[i - 1]); |
| 22 | + } |
| 23 | + |
| 24 | + template <typename InputIt> |
| 25 | + StaticRangeSum(InputIt first, InputIt last) |
| 26 | + : prefix_sum(std::distance(first, last) + 1, Group::identity()) { |
| 27 | + size_t i = 1; |
| 28 | + for (auto it = first; it != last; ++it, ++i) |
| 29 | + prefix_sum[i] = Group::operation(prefix_sum[i - 1], *it); |
14 | 30 | } |
15 | 31 |
|
16 | | - T query(ptr_t l, ptr_t r) const { return prefix_sum[r] - prefix_sum[l]; } |
| 32 | + size_t size() const { return prefix_sum.size() - 1; } |
| 33 | + |
| 34 | + T query(size_t l, size_t r) const { |
| 35 | + if (l > r || r > size()) |
| 36 | + throw std::out_of_range("Invalid range for StaticRangeSum query"); |
| 37 | + return Group::operation(Group::inverse(prefix_sum[l]), prefix_sum[r]); |
| 38 | + } |
17 | 39 | }; |
18 | 40 | } // namespace weilycoder |
19 | 41 |
|
|
0 commit comments