汽油补给
李陶冶 (命题人)
基准时间限制:1 秒 空间限制:131072 KB 分值: 160
有(N+1)个城市,0是起点N是终点,开车从0 -> 1 - > 2…… -> N,车每走1个单位距离消耗1个单位的汽油,油箱的容量是T。给出每个城市到下一个城市的距离D,以及当地的油价P,求走完整个旅途最少的花费。如果无法从起点到达终点输出-1。
例如D = {10, 9, 8}, P = {2, 1, 3},T = 15,最小花费为41,在0加上10个单位的汽油,在1加满15个单位的汽油,在2加2个单位的汽油,走到终点时恰好用完所有汽油,花费为10 * 2 + 15 * 1 + 2 * 3 = 41。
Input
第1行:2个数N, T中间用空格分隔,N + 1为城市的数量,T为油箱的容量(2 <= N <= 100000, 1 <= T <= 10^9)。
第2至N + 1行:每行2个数D[i], P[i],中间用空格分隔,分别表示到下一个城市的距离和当地的油价(1 <= D[i], P[i] <= 1000000)。
Output
输出走完整个旅程的最小花费,如果无法从起点到达终点输出-1。
Input示例
3 15
10 2
9 1
8 3
Output示例
41
思路 : 用数组保存前面比当前站的油价便宜的站点,在考虑当前站点时,优先加前面的站点还可以加的油量,并且每次仅加到刚好能到达下一个站的油量,多余的保存起来
AC代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 1e5 + 10;
typedef long long LL;
int d[MAX],p[MAX];
int main()
{
int n,t,ok = 1,l = 1,r = 1;
LL ans = 0;
scanf("%d %d",&n,&t);
while(n--){
int x,y,sum = 0;
scanf("%d %d",&x,&y);
if(x > t) ok = 0;
if(!ok) continue;
for(int i = l; i < r; i++)
if(p[i] < y) sum += d[i]; // 前面的站的油比当前站便宜,优先加
else r = i; // 不比当前站便宜,没必要在前面站加
if(sum < t) d[r] = t - sum,p[r++] = y; // 当前站可以加油,再跑多远
while(l <= r && x)
if(x < d[l]) ans += (LL)x * p[l],d[l] -= x,x = 0; // 优先在前面站加,因为维护的数组前面的比后面的要便宜
else ans += (LL)d[l] * p[l],x -= d[l++];
}
if(ok) printf("%lld\n",ans);
else puts("-1");
return 0;
}