线段树¶
概述¶
线段树(Segment Tree)是一种强大的**二叉树数据结构**,专门用于高效处理**区间查询**和**区间更新**问题。它能在 O(log n) 时间内完成区间求和、区间最值、区间更新等操作,是算法竞赛和实际应用中常用的数据结构。
核心价值:线段树将数组区间分解为 O(log n) 个不相交的区间段,每个节点存储一个区间的统计信息(如和、最值等),通过分治思想实现高效的区间操作。
为什么需要线段树?¶
线段树结构¶
基本概念¶
| Text Only | |
|---|---|
示例: 数组 [1, 3, 5, 7, 9, 11](索引 0-5)
线段树结构(区间求和):
graph TB
A["[0-5]: 36"] --> B["[0-2]: 9"]
A --> C["[3-5]: 27"]
B --> D["[0-1]: 4"]
B --> E["[2]: 5"]
C --> F["[3-4]: 16"]
C --> G["[5]: 11"]
D --> H["[0]: 1"]
D --> I["[1]: 3"]
F --> J["[3]: 7"]
F --> K["[4]: 9"]
style A fill:#E3F2FD,stroke:#2196F3,stroke-width:2px
style H fill:#E8F5E9
style I fill:#E8F5E9
style E fill:#E8F5E9
style J fill:#E8F5E9
style K fill:#E8F5E9
style G fill:#E8F5E9
| Text Only | |
|---|---|
数组存储方式¶
线段树是完全二叉树,可以用数组存储:
线段树特点¶
1. 区间覆盖¶
每个节点代表一个区间,整棵树覆盖整个数组:
| Text Only | |
|---|---|
2. 完全二叉树¶
线段树是完全二叉树,具有以下优势:
| Text Only | |
|---|---|
3. 懒标记(Lazy Propagation)¶
懒标记是线段树的核心优化技术:
4. 高效查询¶
原理详解¶
建树过程¶
区间查询¶
单点更新¶
区间更新与懒标记¶
懒标记下传(pushDown)¶
可视化演示¶
完整操作演示¶
代码实现¶
线段树结构定义¶
建树¶
区间查询¶
单点更新¶
懒标记下传¶
区间更新¶
带懒标记的查询¶
C++ 实现¶
复杂度分析¶
时间复杂度¶
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| 建树 | O(n) | 每个节点访问一次 |
| 单点查询 | O(log n) | 从根到叶子路径 |
| 单点更新 | O(log n) | 从根到叶子路径 |
| 区间查询 | O(log n) | 访问 O(log n) 个节点 |
| 区间更新 | O(log n) | 使用懒标记 |
空间复杂度¶
- O(n):需要 4n 空间存储线段树和懒标记
线段树的应用¶
1. 区间求和¶
最常见的应用,已在上面详细讲解。
2. 区间最值(RMQ)¶
3. 区间乘积¶
4. 动态规划优化¶
线段树可以优化某些动态规划问题:
5. 扫描线算法¶
| Text Only | |
|---|---|
参考资料¶
- 《算法竞赛入门经典》- 线段树章节
- 《挑战程序设计竞赛》- 数据结构部分
- LeetCode 307. 区域和检索 - 数组可修改
- LeetCode 315. 计算右侧小于当前元素的个数
- 线段树懒标记详解 - CP-Algorithms