#include <concepts>
#include <vector>
#include <vector>
#include <utility>
template <typename Tp, typename Callable>
requires std::regular_invocable<Callable, Tp, Tp>
class segment_tree {
using Ret = typename std::result_of<Callable(Tp, Tp)>::type;
template <typename Up, typename UCallable>
friend class segment_tree;
private:
std::vector<Ret> value {};
std::vector<std::size_t> counter {};
std::size_t length {};
Callable f;
constexpr int left(int x) noexcept { return x << 1; }
constexpr int right(int x) noexcept { return x << 1 |1; }
template <typename Up>
void build(std::ptrdiff_t first, std::ptrdiff_t last, std::size_t index, std::vector<Up> ilist) {
if(first + 1 == last)
return (void) (value[index] = *(ilist.data() + first));
int middle { (first + middle) / 2 };
build(first, middle, left(index), ilist);
build(middle, last, right(index), ilist);
return (void) ( std::exchange(value[index], f(value[left(index)], value[right(index)])) );
}
Ret query(std::ptrdiff_t first, std::ptrdiff_t last, std::ptrdiff_t current_first, std::ptrdiff_t current_last, std::size_t index) noexcept {
if(first <= current_first && last >= current_last) return value[index];
int middle { (current_first + current_last)/2 };
return f(
first < middle ? query(first, last, current_first, middle, left(index)) : 0
, last >= middle ? query(first, last, middle, current_last, right(index)) : 0 );
}
public:
constexpr segment_tree(void) noexcept = default;
explicit segment_tree(segment_tree&&) noexcept = default;
template <typename Up, typename UCallable>
requires std::convertible_to<Up, Tp>
&& std::same_as<Ret, typename segment_tree<Up, UCallable>::Ret>
segment_tree(segment_tree<Up, UCallable> const& other)
: value(other.value)
, counter(other.counter)
, length(other.length)
{}
template <typename Up, typename UCallable>
requires std::convertible_to<Up, Tp>
&& std::same_as<Ret, typename segment_tree<Up, UCallable>::Ret>
segment_tree& operator=(segment_tree<Up, UCallable> other)
{ *this.swap(other); }
template <typename Up, typename UCallable>
requires std::convertible_to<Up, Tp>
&& std::same_as<Ret, typename segment_tree<Up, UCallable>::Ret>
void swap(segment_tree<Up, UCallable> const& other){
value.swap(other.value);
counter.swap(other.counter);
(void) std::exchange(length, other.length);
}
template <typename Up> requires std::convertible_to<Up, Tp>
segment_tree(std::vector<Up> ilist) {
auto length { ilist.size() };
value.resize(length << 1 | 1);
build(0, length, 0, ilist);
}
template <typename Up> requires std::convertible_to<Up, Tp>
void assign(std::vector<Up> ilist)
{ *this.swap(segment_tree(ilist)); }
Ret query(std::ptrdiff_t first, std::ptrdiff_t last) {
return query(first, last, 0, static_cast<std::ptrdiff_t>(length), 0);
}
};
int main(void) {
segment_tree<int, decltype([](int a, int b) { return static_cast<long>(a + b); })> a {std::vector<int>{1, 2, 3, 4, 5, 6}};
}
【线段树的简单封装】
最新推荐文章于 2024-05-20 20:08:58 发布