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

蓝桥杯省赛真题解析:用线段树+优先队列搞定‘小蓝的旅行计划’(附Java完整代码)

蓝桥杯省赛算法精解线段树与优先队列在旅行加油问题中的协同应用第一次看到小蓝的旅行计划这道题时很多选手会被题目中复杂的加油规则和油箱限制条件弄得晕头转向。这道来自蓝桥杯省赛的真题表面上看是一个简单的贪心问题但深入分析后会发现它巧妙地融合了区间维护和动态决策两大算法难点。本文将带你从问题本质出发通过线段树与优先队列的协同工作找到最优解的实现路径。1. 问题重述与核心难点分析题目描述小蓝需要驾驶汽车穿越一系列加油站每个加油站i有三个关键参数到达下一个加油站的距离dis[i]当前加油站的油价cost[i]该加油站单次加油量的上限lim[i]油箱总容量为m要求计算出完成整个旅程的最小油费。如果没有可行方案则返回-1。为什么简单的优先队列解法会失效初看这个问题很多同学会想到用优先队列最小堆来维护油价最低的加油站采用贪心策略每次在油价最低的站点加油。这种方法在没有油箱限制时确实有效但引入油箱容量限制后会出现两个致命问题油量动态变化难以追踪在某站加油后后续站点的剩余油量状态都会改变区间最大值维护需求需要知道两个加油站之间行驶过程中的最大油量消耗// 简单优先队列解法的问题示例 PriorityQueueGasStation queue new PriorityQueue(); queue.addAll(stations); // 无法处理油量限制导致的动态调整2. 算法框架设计双数据结构协同要解决这个难题我们需要设计一个双数据结构系统优先队列负责快速获取当前可选的油价最低加油站线段树实时维护任意区间内的油量最大值2.1 线段树的角色与实现线段树在此问题中主要负责高效处理以下两种操作区间查询查询[i,j]区间内的最大油量值区间更新当在某站加油后更新相关区间的油量值class SegmentTree { int[] maxRest; // 区间最大剩余油量 int[] lazy; // 懒惰标记 void pushUp(int rt) { maxRest[rt] Math.max(maxRest[rt1], maxRest[rt1|1]); } void pushDown(int rt) { if(lazy[rt] ! 0) { lazy[rt1] lazy[rt]; lazy[rt1|1] lazy[rt]; maxRest[rt1] lazy[rt]; maxRest[rt1|1] lazy[rt]; lazy[rt] 0; } } int query(int L, int R, int l, int r, int rt) { if(L l r R) return maxRest[rt]; pushDown(rt); int mid (l r) 1; int res 0; if(L mid) res Math.max(res, query(L, R, l, mid, rt1)); if(R mid) res Math.max(res, query(L, R, mid1, r, rt1|1)); return res; } void update(int L, int R, int val, int l, int r, int rt) { if(L l r R) { lazy[rt] val; maxRest[rt] val; return; } pushDown(rt); int mid (l r) 1; if(L mid) update(L, R, val, l, mid, rt1); if(R mid) update(L, R, val, mid1, r, rt1|1); pushUp(rt); } }2.2 优先队列的优化使用优先队列需要存储加油站信息并按油价排序但需要注意动态调整当某加油站的剩余可加油量为0时需从队列中移除批量处理当油量不足时可能需要连续从多个低价加油站加油PriorityQueueGasStation queue new PriorityQueue( (a, b) - Long.compare(a.cost, b.cost) ); // 加油站类定义 class GasStation { int id; long cost; int limit; // 构造函数等... }3. 关键算法步骤详解3.1 初始化阶段构建空的线段树用于维护各站点的油量信息将所有加油站按油价排序存入优先队列初始化当前油量vol 油箱容量mSegmentTree st new SegmentTree(n); PriorityQueueGasStation queue new PriorityQueue(); for(int i 0; i n; i) { queue.add(new GasStation(i, cost[i], lim[i])); } int vol m;3.2 主循环处理对于每个加油站i1 ≤ i ≤ n消耗dis[i]油量到达该站检查油量是否不足vol 0不足时从优先队列取油价最低的加油站补油处理当前加油站的加油可能性for(int i 1; i n; i) { vol - dis[i]; // 消耗油量到达本站 // 油量不足时的处理 while(vol 0 !queue.isEmpty()) { GasStation best queue.poll(); int maxAdd Math.min( m - st.query(best.id, i-1), // 考虑区间最大油量限制 best.limit // 本站加油上限 ); if(maxAdd 0) continue; if(maxAdd -vol) { // 可以加满需求油量 totalCost best.cost * maxAdd; vol maxAdd; best.limit 0; st.update(best.id, i-1, maxAdd); } else { // 只能加部分油量 totalCost best.cost * (-vol); best.limit maxAdd vol; st.update(best.id, i-1, -vol); queue.add(best); // 放回队列 vol 0; } } if(vol 0) { // 油量仍不足且无加油站可用 System.out.println(-1); return; } // 处理当前加油站 if(vol 0) { st.update(i, i, vol); } queue.add(new GasStation(i, cost[i], Math.min(lim[i], m - vol))); }3.3 复杂度分析该算法的时间复杂度主要来自优先队列操作O(n log n)线段树查询和更新每次O(log n)共O(n log n)总时间复杂度为O(n log n)空间复杂度O(n)完全适用于题目给定的数据范围。4. 完整Java实现与关键注释以下是整合后的完整解决方案包含详细的注释说明import java.util.*; public class TravelPlan { static class GasStation implements ComparableGasStation { int id; long cost; int limit; public GasStation(int id, long cost, int limit) { this.id id; this.cost cost; this.limit limit; } Override public int compareTo(GasStation o) { return Long.compare(this.cost, o.cost); } } static class SegmentTree { int[] maxRest; int[] lazy; int n; public SegmentTree(int n) { this.n n; maxRest new int[4 * n]; lazy new int[4 * n]; } void pushUp(int rt) { maxRest[rt] Math.max(maxRest[rt1], maxRest[rt1|1]); } void pushDown(int rt) { if(lazy[rt] ! 0) { lazy[rt1] lazy[rt]; lazy[rt1|1] lazy[rt]; maxRest[rt1] lazy[rt]; maxRest[rt1|1] lazy[rt]; lazy[rt] 0; } } int query(int L, int R) { return query(L, R, 1, n, 1); } private int query(int L, int R, int l, int r, int rt) { if(L l r R) return maxRest[rt]; pushDown(rt); int mid (l r) 1; int res 0; if(L mid) res Math.max(res, query(L, R, l, mid, rt1)); if(R mid) res Math.max(res, query(L, R, mid1, r, rt1|1)); return res; } void update(int L, int R, int val) { update(L, R, val, 1, n, 1); } private void update(int L, int R, int val, int l, int r, int rt) { if(L l r R) { lazy[rt] val; maxRest[rt] val; return; } pushDown(rt); int mid (l r) 1; if(L mid) update(L, R, val, l, mid, rt1); if(R mid) update(L, R, val, mid1, r, rt1|1); pushUp(rt); } } public static long solve(int m, int[] dis, int[] cost, int[] lim) { int n dis.length - 1; // 假设dis[0]不用从1开始 SegmentTree st new SegmentTree(n); PriorityQueueGasStation queue new PriorityQueue(); for(int i 1; i n; i) { queue.add(new GasStation(i, cost[i], lim[i])); } long totalCost 0; int vol m; for(int i 1; i n; i) { vol - dis[i]; while(vol 0 !queue.isEmpty()) { GasStation best queue.poll(); int maxAdd Math.min( m - st.query(best.id, i-1), best.limit ); if(maxAdd 0) continue; if(maxAdd -vol) { totalCost best.cost * maxAdd; vol maxAdd; best.limit 0; st.update(best.id, i-1, maxAdd); } else { totalCost best.cost * (-vol); best.limit maxAdd vol; st.update(best.id, i-1, -vol); queue.add(best); vol 0; } } if(vol 0) return -1; if(vol 0) { st.update(i, i, vol); } queue.add(new GasStation(i, cost[i], Math.min(lim[i], m - vol))); } return totalCost; } public static void main(String[] args) { // 示例输入 int m 10; int[] dis {0, 2, 3, 5}; // dis[0]不用 int[] cost {0, 3, 2, 4}; // cost[0]不用 int[] lim {0, 5, 3, 2}; // lim[0]不用 long result solve(m, dis, cost, lim); System.out.println(最小油费: result); } }5. 算法优化与边界情况处理在实际编码竞赛中还需要考虑以下优化和边界情况输入输出优化使用BufferedReader代替Scanner处理大规模输入提前终止当油量不足且无加油站可用时立即返回-1初始化检查总距离是否超过初始油量能支持的最大距离零距离站点处理相邻加油站距离为0的特殊情况// 输入优化示例 BufferedReader br new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st new StringTokenizer(br.readLine()); int n Integer.parseInt(st.nextToken()); int m Integer.parseInt(st.nextToken());对于树状数组和线段树的选用虽然两者都能解决区间查询问题但在这个问题中线段树更合适因为需要支持区间更新操作查询的是区间最大值而非简单求和代码结构更清晰易于调试在真实的竞赛场景中建议先写出基础版本确保正确性再根据时间限制决定是否进行常数优化。这道题的解题过程很好地展示了如何将现实问题抽象为算法模型并通过数据结构的组合应用来解决复杂约束条件下的优化问题。

相关文章:

蓝桥杯省赛真题解析:用线段树+优先队列搞定‘小蓝的旅行计划’(附Java完整代码)

蓝桥杯省赛算法精解:线段树与优先队列在旅行加油问题中的协同应用 第一次看到"小蓝的旅行计划"这道题时,很多选手会被题目中复杂的加油规则和油箱限制条件弄得晕头转向。这道来自蓝桥杯省赛的真题,表面上看是一个简单的贪心问题&am…...

倚天剑术46--批量转换其他图片格式为jpg

JPG格式和其他格式相比最大的优点是:保持一定清晰度的基础上具备极高的压缩性。从笔者非专业的角度认为,其实JPG文件除了不支持透明度,其他方面都挺好。因此只要没有透明度的需求,我一般会把图片转换成JPG,占用的空间的…...

Labelme标注数据清洗实战:用Python批量重命名、替换和删除特定标签(附完整代码)

Labelme标注数据清洗实战:Python自动化处理标签体系的三大核心场景 当你完成一轮图像标注后,突然发现标签体系需要调整——可能是命名不规范需要统一,可能是类别定义需要修改,甚至是某些冗余类别需要删除。手动修改每个JSON文件不…...

从SimCLR到CLIP:对比学习在CV领域的演进与落地思考(附避坑指南)

从SimCLR到CLIP:对比学习在视觉智能中的范式跃迁与技术实践 当计算机视觉领域还在为标注数据的稀缺性苦恼时,对比学习像一束光照亮了无监督表征学习的道路。从2020年SimCLR的横空出世,到CLIP开启的多模态新时代,这场技术演进不仅重…...

独立t检验怎么做:软件操作步骤与结果指标解读

一、独立t检验所属模块独立t检验在SPSSAU中归属于【通用方法】模块。二、方法概述独立t检验用于比较两个独立组在某个定量指标上的平均水平是否存在显著差异,常见于性别对比、实验组与对照组对比、不同人群均值比较等场景。对于只有两个组别的差异分析,S…...

如何合并两个表分区_MERGE PARTITIONS合并范围或列表分区

Oracle MERGE PARTITIONS 必须显式指定两个相邻分区名,不支持通配符或FOR VALUES;操作会物理移动数据并锁表,需验证边界值、补全LIST值列表,且DEFAULT分区不可参与合并。ALTER TABLE … MERGE PARTITIONS 语法必须带分区名&#x…...

如何用Sunshine打造终极私人游戏串流平台:5步简单指南

如何用Sunshine打造终极私人游戏串流平台:5步简单指南 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine Sunshine是一款强大的开源游戏串流服务器,专为Moonli…...

基于若依框架的Java多仓库进销存ERP系统源码|SpringBoot+SpringCloud架构|支持试用与二次开发

温馨提示:文末有联系方式系统核心定位 本系统是一款面向中小企业的现代化网络版ERP解决方案,深度融合进销存管理与多仓库协同能力,采用主流Java技术栈构建,具备高扩展性与模块化设计特点。技术架构亮点 系统基于开源若依&#xff…...

CKS考试通关后,我总结的这16个K8s安全加固实战场景(含详细命令)

CKS认证工程师必备:16个Kubernetes生产级安全加固场景深度解析 在云原生技术快速发展的今天,Kubernetes已成为企业容器编排的事实标准,但随之而来的安全挑战也日益严峻。作为通过CKS认证的工程师,我们不仅需要掌握考试要求的修复技…...

Zephyrus Duo 双屏游戏本体验超酷但价格贵,与竞品相比性能和成本谁更优?

Zephyrus Duo 亮点与目标用户这款笔记本电脑亮点颇多,配备两块全尺寸 16 英寸 OLED 屏幕、顶级的 Nvidia RTX 5090 笔记本 GPU、近乎顶级的 16 核英特尔 Panther Lake 芯片等。不过,它似乎没有明确的目标用户,但能带来超酷且有趣的使用体验。…...

魔兽争霸3终极优化指南:5分钟解决所有兼容性问题

魔兽争霸3终极优化指南:5分钟解决所有兼容性问题 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为经典游戏《魔兽争霸3》在现代电脑上…...

主从DNS服务器实验

【实验要求】:完成DNS的主服务器配置完成DNS的从服务器配置完成客户端配置【步骤】:一、DNS主服务器配置登录主服务器,完成IP等一切先前配置后,安装bind,进入目录/etc编辑主配置文件named.confvim /etc/named.conflist…...

Transformer在文档级事件抽取中的应用与优化

1. 项目背景与核心价值MAVEN-FACT数据集是近年来事件抽取领域的重要基准测试集,包含超过4,800个文档和118,732个事件实例。这个项目最吸引我的地方在于它首次将事件抽取任务从传统的句子级扩展到了文档级,更贴近真实场景中的信息处理需求。我在处理客户舆…...

【MySQL | 第八篇】索引的使用

目录 一、索引的使用规则 1.最左前缀法则 2.范围查询 3.索引的失效情况 3.1索引列运算 3.2字符串不加引号 3.3模糊查询 3.4or连接的条件 3.5数据分布影响 4.SQL提示 5.覆盖索引⭐⭐⭐⭐⭐ 6.前缀索引 7.单列索引与联合索引 二、索引的涉及原则 一、索引的使用规则…...

Wand-Enhancer:免费解锁WeMod高级功能的完整指南

Wand-Enhancer:免费解锁WeMod高级功能的完整指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 你是否厌倦了WeMod游戏助手的付费限制&…...

别再被5V电源坑了!ESP32-CAM搭配CH340烧录与运行的全流程避坑指南

ESP32-CAM电源与烧录终极指南:从硬件连接到稳定运行 刚拿到ESP32-CAM开发板时,那种跃跃欲试的兴奋感很快会被一连串的硬件问题浇灭——电源接3.3V无法启动、CH340接线错误导致烧录失败、IO0引脚状态不对让设备"装死"。这些问题困扰着每一位刚接…...

从短期利率到波动率:手把手用Python复现CIR模型,搞定金融时间序列模拟

从短期利率到波动率:手把手用Python复现CIR模型,搞定金融时间序列模拟 金融市场的波动性和利率变化常常让分析师们头疼不已。想象一下,你手头有一组历史利率数据,老板突然要求你预测未来半年可能出现的极端情景——这可不是靠直觉…...

Go 语言从入门到进阶 | 第 16 章:反射(Reflection)

系列:Go 语言从入门到进阶 作者:耿雨飞 适用版本:go v1.26.2 前置条件 在开始本章学习之前,请确保: 已完成第 6 章(接口与多态)的学习,理解接口的动态类型和动态值 已完成第 4 章(复合数据类型)的学习,熟悉结构体和标签语法 已获取 Go 1.26.2 源码树(go-go1.26.2 …...

用STM32F103和VS1053B手搓一个MP3播放器:从SD卡读取到OLED显示的完整流程

用STM32F103和VS1053B打造高保真MP3播放器:从硬件搭建到软件优化的全流程解析 在嵌入式音频开发领域,DIY一个具备完整功能的MP3播放器始终是检验开发者系统设计能力的经典项目。本文将基于STM32F103微控制器与VS1053B解码芯片的组合,深入剖析…...

Claude Code 十大必装 MCP 排行榜(2026年最新版)

🏆 Claude Code 十大必装 MCP 排行榜(2026年最新版) 作为一名重度使用 Claude Code 的开发者,我踩过不少坑,也发现了许多能极大提升开发效率的 MCP。今天就把我心目中最值得安装的10个 MCP 整理出来,附带详…...

Synopsys AXI VIP实战:除了outstanding检查,回调机制还能帮你做哪些事?

Synopsys AXI VIP回调机制深度实战:解锁验证效率的五大高阶技巧 AXI总线作为现代SoC设计的核心互联标准,其验证复杂度随着系统规模呈指数级增长。Synopsys验证IP(VIP)提供的回调机制,就像给验证工程师配备了一把瑞士军…...

如何搭建个人游戏串流服务器:Sunshine完整指南

如何搭建个人游戏串流服务器:Sunshine完整指南 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine Sunshine是一款开源的游戏串流服务器,能够将高性能电脑上的游…...

实战解析:在华为云Stack(HCS 6.5)中如何为Oracle RAC规划BMS裸金属与高性能云硬盘

华为云Stack 6.5环境下Oracle RAC的裸金属与存储架构设计指南 当企业将Oracle RAC这类关键数据库迁移到私有云环境时,基础设施的规划直接决定了业务系统的稳定性和性能表现。华为云Stack 6.5(HCS)作为成熟的私有云解决方案,其BMS裸…...

告别双系统折腾!用Python工具rosbags一键搞定ROS1/ROS2的bag文件互转

告别双系统折腾!用Python工具rosbags一键搞定ROS1/ROS2的bag文件互转 在机器人开发领域,数据记录与回放是调试和验证算法的重要环节。ROS1和ROS2作为机器人操作系统的主流版本,各自采用不同的数据存储格式,这给开发者带来了不小的…...

海外短剧APP开发,从0到1:硬刚谷歌商店合规,打通海外多币种支付!

短剧出海“掘金”正当时,但很多团队在第一步就卡住了:APP 被谷歌商店拒审、支付掉单严重、封号风险高。相比 H5 的灵活,APP 虽然周期长,但 留存和 LTV 更高,是建立品牌壁垒的必选项。 今天就聊聊如何开发一款符合谷歌…...

番茄小说下载器:构建个人数字图书馆的高效解决方案

番茄小说下载器:构建个人数字图书馆的高效解决方案 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 还在为网络不稳定无法畅快阅读而烦恼吗?这款基于Rus…...

大语言模型偏见量化实战(R语言统计框架全公开)

更多请点击: https://intelliparadigm.com 第一章:大语言模型偏见量化的基本概念与R语言生态定位 大语言模型(LLM)偏见量化是指通过可复现的统计指标与实验范式,系统性地测量模型在性别、种族、地域、职业等维度上输出…...

【VS Code MCP插件生态架构白皮书】:20年IDE架构师亲授从零搭建高兼容、可扩展、易维护的MCP服务层(含4层抽象设计图+3大协议适配范式)

更多请点击: https://intelliparadigm.com 第一章:VS Code MCP插件生态搭建手册 MCP 协议与 VS Code 集成原理 MCP(Model Context Protocol)是面向大模型工具调用的开放协议,VS Code 通过官方语言服务器协议&#xf…...

如何实现ComfyUI-Manager离线部署:3种本地安装方案详解

如何实现ComfyUI-Manager离线部署:3种本地安装方案详解 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable various cust…...

数字线程:数字孪生的“中枢神经”,如何驱动产业智能升级?

数字线程:数字孪生的“中枢神经”,如何驱动产业智能升级? 引言 (配图建议:一张对比图,左侧是分散、断裂的传统数据流,右侧是通过一条光带“数字线程”串联起的全生命周期数据闭环。)…...