1. 旅行加油问题与数据结构选型
遇到蓝桥杯这道旅行加油题时,很多选手的第一反应是用贪心算法解决。确实,如果没有油箱容量限制,直接用优先队列选择最便宜的加油站加油就能搞定。但现实情况往往更复杂——油箱有容量上限,每次加油量还受加油站限制,这时候就需要更精巧的数据结构组合。
我最初尝试用纯优先队列解题时,发现无法处理"加油后影响后续站点油量"这个关键约束。比如在A站加了10升油,到达B站时油箱剩余量会影响B站的最大可加油量。这种区间影响特性让我联想到线段树的经典应用场景。而优先队列的优势在于能快速获取当前最优解,两者结合正好互补。
这里有个生活化的类比:想象你开车穿越沙漠,优先队列就像随时帮你找到最便宜油价的导航,而线段树则是精确计算每个路段油耗的智能油箱。只有两者配合,才能既省钱又不抛锚。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 线段树维护区间最大值的实现细节
2.1 线段树结构设计
我们需要线段树维护的关键信息是:从加油站j到当前站点的最大剩余油量。这个值决定了在j站能加多少油而不溢出油箱。代码中的rest[]数组就是为此设计:
java复制static int rest[] = new int [maxn<<2]; // 四倍空间标准写法
static int k[] = new int [maxn<<2]; // 懒标记数组
static void up(int i) {
rest[i] = Math.max(rest[i<<1], rest[i<<1|1]); // 取左右子树最大值
}
建树时初始化所有节点油量为0,因为尚未到达任何加油站。注意这里采用了递归建树的经典写法,时间复杂度O(n):
java复制static void build(int i,int l,int r) {
if(l == r) {
rest[i]=0; // 初始油量0
return ;
}
int mid = (l+r)/2;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
up(i); // 上推更新
}
2.2 区间查询与更新
当在j站加油后,需要更新j到当前站点的油量信息。这里用到
