【线段树的简单封装】

#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}};

}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值