当前位置: 首页 > news >正文

可持久化线段树(Persistent Segment Tree)详解

1. 什么是可持久化线段树

可持久化线段树(Persistent Segment Tree),又称主席树,是一种能够保存历史版本的数据结构。它在普通线段树的基础上,通过复用未修改的节点来创建新的版本,从而在O(log n)的时间复杂度内支持对历史版本的查询和修改。

2. 核心思想

可持久化线段树的核心思想是节点复用:当修改某个节点时,只创建该节点的新副本,而其他未修改的节点则直接指向旧版本的节点。这样每个版本都对应一棵完整的线段树,但不同版本之间共享了大量节点。

3. 数据结构设计

每个节点需要存储以下信息:

  • 左子节点指针
  • 右子节点指针
  • 节点维护的值(如区间和、最大值等)

4. 基本操作

4.1 建树

struct Node { int l, r; // 左右子节点编号 int sum; // 区间和 } tr[N * 40]; // 需要开足够大的空间 int build(int l, int r) { int p = ++idx; if (l == r) { tr[p].sum = a[l]; return p; } int mid = (l + r) >> 1; tr[p].l = build(l, mid); tr[p].r = build(mid + 1, r); tr[p].sum = tr[tr[p].l].sum + tr[tr[p].r].sum; return p; }

4.2 单点更新

int update(int pre, int l, int r, int pos, int val) { int p = ++idx; tr[p] = tr[pre]; // 复制原节点 if (l == r) { tr[p].sum = val; return p; } int mid = (l + r) >> 1; if (pos <= mid) tr[p].l = update(tr[pre].l, l, mid, pos, val); else tr[p].r = update(tr[pre].r, mid + 1, r, pos, val); tr[p].sum = tr[tr[p].l].sum + tr[tr[p].r].sum; return p; }

4.3 区间查询

int query(int p, int l, int r, int ql, int qr) { if (ql <= l && r <= qr) return tr[p].sum; int mid = (l + r) >> 1, res = 0; if (ql <= mid) res += query(tr[p].l, l, mid, ql, qr); if (qr > mid) res += query(tr[p].r, mid + 1, r, ql, qr); return res; }

5. 经典应用

5.1 静态区间第k小

这是主席树最经典的应用。通过对值域建立可持久化线段树,每个版本对应前缀[1, i]中各个数值出现的次数。

5.2 可持久化数组

支持历史版本的数组单点修改和查询。

5.3 树上路径查询

结合树链剖分或树上差分,可以处理树上路径的查询问题。

6. 时空复杂度分析

  • 时间复杂度:每次操作O(log n)
  • 空间复杂度:O(n log n),因为每次修改只会创建O(log n)个新节点

7. 注意事项

  1. 需要预先估算节点数量,一般开N * 40的空间
  2. 注意版本号的存储和管理
  3. 离散化可以减小值域,降低空间消耗
  4. 合理设计节点信息,避免冗余存储

8. 总结

可持久化线段树是一种功能强大的数据结构,特别适合需要访问历史版本的场景。虽然实现相对复杂,但掌握了其核心思想和实现技巧后,能够解决许多传统数据结构难以处理的问题。

http://www.jsqmd.com/news/1310591/

相关文章:

  • Unlimited-OCR 部署运行(11/13):环境变量块超限导致 spawn 子进程崩溃
  • 围棋AI智能教练KaTrain:免费开源工具助你快速提升棋力的终极指南
  • DSL崛起挑战Python生态:领域特定语言如何重塑开发者技能与薪酬
  • 2026下半年珠海古堡瓷砖实力厂商甄选:广东乐高尚品陶瓷以全案美学破局同质化 - 装修教育财税推荐2026
  • 如何用Zettelkasten打造你的第二大脑:免费开源知识管理终极指南
  • 从零打造64x64高密度全彩LED矩阵:HUB75接口驱动与ESP32实战
  • 变频无刷电机低噪音控制实战:从FOC原理到35分贝静音实现
  • 2026年8月湖南省电信2000M融合宽带实测对比宽带怎么选? - 找卡家园
  • RTL8019AS、555,DS3231等芯片的跳线方式和引脚定义
  • GD32F450Z移植LittleFS:构建掉电安全的SPI Flash存储方案
  • 2026年8月湖南省联通500M单宽带申请避坑实录 - 找卡家园
  • DSO Quad示波器固件构建:从STM32开发环境搭建到固件烧录全流程
  • [特殊字符]2026奇幻新片《星光继承者:暗黑仙境》 4K DVHDR超清画质,内封简中字幕 夸克网盘分享,支持在线观看!
  • Windows驱动管理的终极免费工具:Driver Store Explorer完整使用指南
  • 树莓派5寸HDMI显示屏选购配置全攻略:从参数解析到实战优化
  • 昆明理工大学信息工程与自动化2026届硕士就业流向全景解析
  • 2026年8月湖南省怀化市移动单宽带小白避坑指南 - 找卡家园
  • BepInEx IL2CPP插件框架崩溃问题的完整修复指南
  • 忍者龙剑传4豪华版免费下载
  • PL2303 USB转串口模块:从驱动安装到电平匹配的实战指南
  • C++链表尾插法:从原理到工程实践,告别头插法逆序问题
  • HarmonyOS 三方 SDK 接入治理实战:用途审核、能力隔离、运行监控与可退出
  • 迷宫生成算法可视化:从DFS到Kruskal,四种经典算法实现与对比
  • 2026年8月湖南省联通500M单宽带申请避坑全攻略 - 找卡家园
  • 2026年8月湖南省电信2000M融合宽带申请避坑实录 - 找卡家园
  • 【AI大模型进阶】流式输出(Streaming):让AI逐字回复,体验“打字机”的快感
  • VirtualBox虚拟机存储路径迁移全攻略:释放C盘空间与优化文件管理
  • Windows Phone模拟器WPR Alpha部署与XAP应用运行实战指南
  • 如何用CompressO快速压缩视频图片:面向新手的终极免费工具指南
  • 2026年8月湖南省怀化市移动单宽带申请避坑攻略 - 找卡家园