【树状数组 | 简单实现】(单点修改 | 区间查询)

#include <functional>
#include <array>
#include <concepts>
#include <iostream>
#include <limits>

constexpr int __MAX__ { static_cast<int>( 1e4 ) * 2 };

constexpr int lowbit(signed x) noexcept {
	return std::bit_and<signed> {}(x, std::negate<signed> {}(x));
}

template <typename T, typename... U>
concept all_of_same_as = (std::same_as<T, U> && ...);


//初始化
template <typename... Args>
auto convert(Args ...args)
	requires (all_of_same_as<signed, Args...>){
	constexpr auto length { static_cast<int>(sizeof...(Args)) };
	constexpr auto place_holder { std::numeric_limits<signed>::min() };
	std::array<signed, length + 1> from {place_holder, args...};
	std::array<long long signed, length + 1> transformed { {place_holder, 0, } };
	for(auto i {1}; i <= length; ++i)
		for(auto j {i - lowbit(i) + 1}; j <= i; ++j)
			transformed[i] += from[j];
	return transformed;
}

//前缀和
template <std::size_t Size>
constexpr auto prefix(std::array<long long signed, Size> const & transformed, int p) noexcept{
	long long signed result {};
	for(; p; p -= lowbit(p)) result += transformed[p];
	return result;
}

//区间和
template <std::size_t Size>
constexpr auto range_sum(std::array<long long signed, Size> const & transformed, int p, int q) noexcept{
	return prefix(transformed, q) - prefix(transformed, p - 1);
}

//单点修改
template <std::size_t Size>
constexpr void single_modify(std::array<long long signed, Size> & transformed, int p, int x) noexcept{
	for(; p < static_cast<int>(Size); p += lowbit(p)) transformed[p] += x;
}

//测试
int main(void){
	auto result { convert(1, 2, 3, 4, 5, 6, -3) };
	for(auto e : result) std::cout << e << ' ';
	endl(std::cout);
	std::cout << prefix(result, 3);
	endl(std::cout);
	single_modify(result, 1, 1);
	for(auto e : result) std::cout << e << ' ';
	endl(std::cout);
	std::cout << range_sum(result, 1, 4);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为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、付费专栏及课程。

余额充值