【算法随笔:线段树 Segment tree】(多操作 | leetcode例题)

目录

分析

 DSA模板(静态数组、侵入式)

线段树经典应用

1 逆序数

2 矩形区间并


分析

线段树每种操作的实现区别的细粒度高,不好封装,并且一般在算法题中出现。

线段树代码量很大

线段树具有堆结构,一般采用静态数组实现最优,当然动态树也可以,改天更新

线段树处理动态修改查询区间非常强大,很少有别的数据结构能与之媲美

线段树进阶操作还有持久化,操作回溯,优化建图,树上二分等,这些扩展持续学习中,改日更新

 DSA模板(静态数组、侵入式)

Version I : 单点赋值 + 区间加法查询

Version II: 单点加法 + 区间加法查询

Version III:  区间赋值 + 区间加法查询

Version IV: 区间加法 + 区间最小值查询

Version V: 区间加法 + 区间最小值计数 + 区间最小值查询

一下代码,自行参考学习

/*
* 	static (instrusive and non-generic) segment tree implemented based on linear integral array
* 	generally, the DSA arc supports those operations onto an integer array:
* 		1: single point modify(assignment) [ array[index] = value ]
*		2: range modify 
			2.1: assignment[ array[first : last : 1 step] = value ]
			2.2: addition[ array[first : last : 1 step] += value ]
		3: range query 
			3.1 query by addition [ SumOf{ array[first : last : 1 step] } ]
			3.2 query be minimum [ MinOf{ array[first : last : 1 step] } ]
				3.2.0 query by minimum while recording the count [ CountOf{ MinOf{ array[first : last : 1 step] } } ]
*/

/*
*	version I
* 	only support [single point modify] and [segment query by the [addition] at certain ranges]
*/

#if defined(SINGLE_POINT_MODIFY) && defined(SEGMENT_QUERY) && defined(UPDATE_ADDITION)

#include <array>
constexpr auto __MAX__ { static_cast<int>(1e3) };
std::array<int, __MAX__ + 1> sequence {};
std::array<int, __MAX__ << 2 | 1> addition {};
constexpr int left(int index) noexcept { return x << 1; }
constexpr int right(int index) noexcept { return x << 1 | 1; }
constexpr void update(int index) noexcept {
	addition[index] = addition[left(index)] + addition[right(index)];
}

void build(int first, int last, int index) noexcept {
	if(first + 1 == last) 
		return (void) { addition[first] = sequence[first] };
	int middle { (first + last) / 2 };
	build(first, middle, left(index));
	build(middle, last, right(index));
	update(index);
}

int query(int first, int last, int current_first, int current_last, int index) noexcept {
	if(first <= current_first && last >= current_last) return addition[index];
	int middle { (current_first + current_last)/2 };
	return (
		first < middle ? query(first, last, current_first, middle, left(index)) : 0
	+	last >= middle ? query(first, last, middle, current_last, right(index)) : 0 );
}

void change(int position, int value, int first, int last, int index) noexcept {
	if(first + 1 == last) return (void) (addition[index] = v);
	int middle { (first + last)/2 };
	if(position < middle) change(position, value, first, middle, left(index));
	else change(position, value, middle, last, right(index));
	update(index);
}

#endif

/*
*	version II
* 	only support [range modify] and [segment query by the [addition] at certain ranges]
*/

#if defined(RANGE_MODIFY) && defined(SEGMENT_QUERY) && defined(UPDATE_ADDITION)

#include <array>
constexpr auto __MAX__ { static_cast<int>(1e3) };
std::array<int, __MAX__ + 1> sequence {};
std::array<int, __MAX__ << 2 | 1> addition {};
std::array<int, __MAX__ << 2 | 1> lazy {};
constexpr int left(int index) noexcept { return x << 1; }
constexpr int right(int index) noexcept { return x << 1 | 1; }
constexpr void update(int index) noexcept {
	addition[index] = addition[left(index)] + addition[right(index)];
}

void build(int first, int last, int index) noexcept {
	if(first + 1 == last) 
		return (void) { addition[first] = sequence[first] };
	int middle { (first + last) / 2 };
	build(first, middle, left(index));
	build(middle, last, right(index));
	update(index);
}

void down(int first, int last, int index) noexcept {
	int middle { (first + last) / 2 };
	if(lazy[index] > 0) {
		lazy[left(index)] = lazy[right(index)] = lazy[index];
		addition[left(index)] = (middle - first) * lazy[index];
		addition[right(index)] = (last - middle) * lazy[index];
		lazy[i
评论 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、付费专栏及课程。

余额充值