线段树实现区间最小值查询与修改的算法详解
1. 问题背景与需求分析TZOJ 3315题目买火车票(线段树区间最小值)是一个典型的区间查询问题。题目要求我们处理一个序列支持两种操作区间最小值查询和区间修改。这类问题在实际应用中非常常见比如火车票余票查询系统、库存管理系统等场景。核心需求可以分解为高效查询任意区间的最小值支持对区间进行修改操作在大量查询和修改操作下保持较好的时间复杂度2. 线段树数据结构解析线段树是一种二叉树结构特别适合处理区间查询问题。对于这个问题我们需要构建一个能够维护区间最小值的线段树。2.1 线段树节点设计每个线段树节点需要存储以下信息区间范围[l, r]当前区间的最小值min_val延迟标记lazy_tag用于区间修改的优化struct SegmentTreeNode { int l, r; int min_val; int lazy_tag; };2.2 线段树构建构建线段树的过程是一个递归分治的过程void build(int u, int l, int r) { tree[u].l l; tree[u].r r; tree[u].lazy_tag 0; if(l r) { tree[u].min_val a[l]; return; } int mid (l r) 1; build(u 1, l, mid); build(u 1 | 1, mid 1, r); push_up(u); }3. 关键操作实现3.1 区间最小值查询查询区间[L, R]的最小值int query_min(int u, int L, int R) { if(tree[u].l L tree[u].r R) { return tree[u].min_val; } push_down(u); // 处理延迟标记 int mid (tree[u].l tree[u].r) 1; int res INT_MAX; if(L mid) res min(res, query_min(u 1, L, R)); if(R mid) res min(res, query_min(u 1 | 1, L, R)); return res; }3.2 区间修改操作实现区间修改如区间赋值void modify(int u, int L, int R, int val) { if(tree[u].l L tree[u].r R) { tree[u].min_val val; tree[u].lazy_tag val; return; } push_down(u); int mid (tree[u].l tree[u].r) 1; if(L mid) modify(u 1, L, R, val); if(R mid) modify(u 1 | 1, L, R, val); push_up(u); }4. 延迟标记技术详解延迟标记Lazy Propagation是线段树的核心优化技术它允许我们将修改操作延迟到真正需要时才执行。4.1 标记下传实现void push_down(int u) { if(tree[u].lazy_tag) { int val tree[u].lazy_tag; tree[u 1].min_val val; tree[u 1].lazy_tag val; tree[u 1 | 1].min_val val; tree[u 1 | 1].lazy_tag val; tree[u].lazy_tag 0; } }4.2 标记上传实现void push_up(int u) { tree[u].min_val min(tree[u 1].min_val, tree[u 1 | 1].min_val); }5. 复杂度分析与优化5.1 时间复杂度建树O(n)查询O(log n)修改O(log n)5.2 空间优化技巧对于完全二叉树可以使用数组而非指针来表示树结构节省空间SegmentTreeNode tree[4 * MAX_N]; // 通常开4倍空间足够6. 实际应用中的注意事项边界条件处理特别注意查询区间与当前节点区间的包含关系初始值设置根据问题需求设置合适的初始值和标记数据类型选择根据数值范围选择合适的变量类型递归深度对于极大区间考虑非递归实现避免栈溢出7. 完整代码实现#include iostream #include algorithm #include climits using namespace std; const int MAX_N 1e5 5; struct SegmentTreeNode { int l, r; int min_val; int lazy_tag; } tree[4 * MAX_N]; int a[MAX_N]; void push_up(int u) { tree[u].min_val min(tree[u 1].min_val, tree[u 1 | 1].min_val); } void push_down(int u) { if(tree[u].lazy_tag) { int val tree[u].lazy_tag; tree[u 1].min_val val; tree[u 1].lazy_tag val; tree[u 1 | 1].min_val val; tree[u 1 | 1].lazy_tag val; tree[u].lazy_tag 0; } } void build(int u, int l, int r) { tree[u].l l; tree[u].r r; tree[u].lazy_tag 0; if(l r) { tree[u].min_val a[l]; return; } int mid (l r) 1; build(u 1, l, mid); build(u 1 | 1, mid 1, r); push_up(u); } void modify(int u, int L, int R, int val) { if(tree[u].l L tree[u].r R) { tree[u].min_val val; tree[u].lazy_tag val; return; } push_down(u); int mid (tree[u].l tree[u].r) 1; if(L mid) modify(u 1, L, R, val); if(R mid) modify(u 1 | 1, L, R, val); push_up(u); } int query_min(int u, int L, int R) { if(tree[u].l L tree[u].r R) { return tree[u].min_val; } push_down(u); int mid (tree[u].l tree[u].r) 1; int res INT_MAX; if(L mid) res min(res, query_min(u 1, L, R)); if(R mid) res min(res, query_min(u 1 | 1, L, R)); return res; } int main() { int n, m; cin n m; for(int i 1; i n; i) { cin a[i]; } build(1, 1, n); while(m--) { int op, l, r; cin op l r; if(op 1) { // 查询区间最小值 cout query_min(1, l, r) endl; } else { // 区间修改 int val; cin val; modify(1, l, r, val); } } return 0; }8. 性能优化与扩展8.1 多标记处理对于同时存在多种修改操作如加法和赋值的情况需要设计更复杂的标记处理逻辑struct AdvancedTag { int add; int set; bool has_set; };8.2 动态开点线段树当区间范围很大但实际使用点稀疏时可以采用动态开点技术节省内存struct DynamicNode { int lc, rc; // 左右子节点编号 int min_val; int lazy_tag; };8.3 可持久化线段树如果需要保存历史版本可以实现可持久化线段树int clone(int u) { tot; tree[tot] tree[u]; return tot; }9. 常见问题与调试技巧区间划分错误确保mid计算和区间划分正确标记处理遗漏在任何递归访问子节点前都要下传标记初始值问题根据问题需求设置合适的初始极值数组越界确保线段树数组大小足够通常4倍原始数据大小调试时可以添加打印函数输出线段树的当前状态void print_tree(int u) { cout Node u : [ tree[u].l , tree[u].r ] min tree[u].min_val tag tree[u].lazy_tag endl; if(tree[u].l tree[u].r) return; print_tree(u 1); print_tree(u 1 | 1); }10. 实际应用案例以火车票系统为例假设每个座位区间[a,b]的票价为val我们可以用线段树维护每个座位区间的最小票价查询时找到满足价格要求的最低票价区间购票后更新相应区间的余票信息这种实现可以高效处理大量并发的查询和购票请求。

相关新闻

Unity Timeline入门:5分钟掌握物体激活与动画序列控制

Unity Timeline入门:5分钟掌握物体激活与动画序列控制

1. 项目概述:为什么Unity Timeline是动画控制的“瑞士军刀”?如果你正在Unity里捣鼓一个过场动画,或者想让几个物体按顺序动起来,是不是还在写一堆Invoke或者Coroutine来手动控制SetActive和Animator.Play?每次改个时间…

2026/7/20 8:00:23阅读更多 →
网页打包APP完整指南:从WebView原理到实战优化

网页打包APP完整指南:从WebView原理到实战优化

你是不是曾经遇到过这样的场景:想把某个经常访问的网站变成手机上的APP,方便一键打开,但又不想花时间学习复杂的原生APP开发?或者作为开发者,客户要求快速将他们的官网打包成APP,但预算和时间都很有限&…

2026/7/20 7:38:10阅读更多 →
Kimi K3大模型代码生成与长文本处理实践指南

Kimi K3大模型代码生成与长文本处理实践指南

这次我们来看一下 Kimi K3 模型的正式亮相。作为月之暗面(Moonshot AI)推出的最新一代大语言模型,Kimi K3 在代码生成、长文本处理和推理能力方面都有显著提升。对于需要高效编程辅助、长文档分析或多轮对话的开发者和技术团队来说&#xff0…

2026/7/20 16:24:20阅读更多 →
2026电钢琴参数拆解攻略|看懂核心配置,6款实测机型推荐

2026电钢琴参数拆解攻略|看懂核心配置,6款实测机型推荐

绝大多数新手选购电钢琴时,都会被繁杂的专业参数劝退:逐级配重、复音数值、音源采样、DSP音效……分不清哪些是核心硬配置,哪些是无关营销噱头。很多人盲目高价入手溢价机型,或是低价买到缩水款,练琴体验极差&#xff…

2026/7/21 1:26:05阅读更多 →
深入解析SoC功耗管理:动态依赖、唤醒机制与PRCM模块实战

深入解析SoC功耗管理:动态依赖、唤醒机制与PRCM模块实战

1. 项目概述与核心价值在嵌入式系统,尤其是汽车电子、移动设备这类对功耗和性能都极为敏感的领域,如何让一块复杂的SoC芯片(System on Chip)既能在需要时“火力全开”,又能在空闲时“深度休眠”,是每一位底…

2026/7/21 1:26:05阅读更多 →
Chrome 49 在 ReactOS 上 c0000005 崩溃的修复过程

Chrome 49 在 ReactOS 上 c0000005 崩溃的修复过程

Chrome 49 在 ReactOS 上 c0000005 崩溃的修复过程 概述 Chrome 49 (Chrome_V49) 在 ReactOS 上启动时立即崩溃,异常代码 c0000005(访问违例),EIP0。本文档详细记录了从问题分析到修复的完整过程。1. 启用 Chrome 专用崩溃调试日志…

2026/7/21 1:26:05阅读更多 →
机器学习模型生产化落地:从Notebook到高可靠服务的全链路实践

机器学习模型生产化落地:从Notebook到高可靠服务的全链路实践

1. 项目概述:当模型走出Jupyter,真正开始呼吸真实世界空气“From Notebook to Production: Running ML in the Real World (Part 4)”——这个标题本身就像一句暗号,懂的人立刻会心一笑。它不是在讲怎么调参、怎么画loss曲线,而是…

2026/7/21 1:26:05阅读更多 →
Uber机器学习工程实践:从模型上线到系统稳态的落地指南

Uber机器学习工程实践:从模型上线到系统稳态的落地指南

1. 项目概述:当机器学习走出实验室,撞上真实世界的“水泥墙”我第一次在生产环境里部署一个推荐模型时,信心满满地敲下kubectl apply -f model-deployment.yaml,结果三分钟后告警邮件就堆满了收件箱——API延迟从200ms飙到8秒&…

2026/7/21 1:26:05阅读更多 →
校园竞赛管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

校园竞赛管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

博主介绍:🌟 个人简介 CSDN特邀作者 | 掘金优质创作者,深耕Java生态与现代Web开发技术栈。专业领域涵盖Java企业级开发、Spring Boot微服务架构、前后端分离解决方案,以及学术项目的工程化实践。 📊 影响力数据 全平台…

2026/7/21 1:24:04阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

📌教程适配:OpenClaw v2.7.9 | 兼容 Windows10/11、macOS 双系统 📖前言 当下各类本地 AI 工具层出不穷,多数产品仅能完成文字问答交互,很难直接操控电脑执行实际操作。OpenClaw,业内常称小龙虾 AI&#…

2026/7/21 0:01:46阅读更多 →
Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

聊《一次Codex项目复盘,问题最后出在流程而不是模型》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要先把这篇文章的目标说清楚:看完之后,你应该能判断这件事值不值得做&…

2026/7/21 0:01:46阅读更多 →
手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

大家好,还是我。前几期带大家做了心情日记本和可视化大屏,后台有朋友留言:“能不能教点好玩的?我想做游戏,但一行代码都不会。”行,这期就安排。今天的目标:从零做一个五子棋游戏。 带AI对战、三…

2026/7/21 0:03:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/20 22:51:39阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/20 18:51:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/20 18:51:18阅读更多 →