洛谷P9749 [CSP-J 2023] 公路 题解

本题做法

  • 前缀和思想、模拟和贪心。

思路

定义一个数组 \(pre[i]\) 表示油价数组 \(a\)\(a[1]\sim a[i]\) 中的最小油价,递推公式为 \(pre[i]=\min\{pre[i-1], a[i]\}(i>1),pre[1]=a[1]\)。遍历距离数组 \(v\)\(1\sim n-1\)(因为第 \(n\) 站没有后续站点了),每次算出需要购买的油量(注意:这里有坑!需要使用 double 存储上一次加油剩下的油量,详见样例 1 的第二站。且油量需要向上取整。)乘上 \(pre[i]\),所有的乘积相加得到结果。公式就是

\[\sum_{i=1}^{n-1}{pre[i]\times ⌈v[i]\div d-s⌉(其中s为剩余的油量,计算公式为s=⌈v[i]\div d-s⌉+s-v[i]\div d)} \]

代码

#include<bits/stdc++.h>

using namespace std;

const int INF=0x3f3f3f3f;
const double EPS=1e-8;
const int N=1e5+5;

long long n,d,p,v[N],pre[N],a[N];
long double s;

int main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	cin>>n>>d;
	for(int i=1;i<n;i++) cin>>v[i];
	for(int i=1;i<=n;i++) {
		cin>>a[i];
		if(i==1) pre[i]=a[i];
		else pre[i]=min(pre[i-1],a[i]);
	}
	for(int i=1;i<n;i++){
		p+=ceil(1.0*v[i]/d-s)*pre[i];
		s=ceil(1.0*v[i]/d-s)+s-1.0*v[i]/d;
	}
	cout<<p;
	return 0;
}
posted @ 2025-06-24 20:22  2789617221guo  阅读(105)  评论(0)    收藏  举报