[10.3模拟赛]T2

Description

\(Jim\)是一个胆小的男生,可是每天他都要学习到很晚才能回家,而且他回家的路上没有路灯。
\(Jim\)非常怕黑,万幸的是他还有一个手电筒可以用,我们设手电筒的电量上限为\(T\)
\(Jim\)回家的路上有\((N+1)\)个充电站,\(0\)是起点\(N\)是终点,\(Jim\)每走一个单位距离消耗\(1\)个单位的电量。
给出每个充电站到下一个充电站的距离\(D\),以及充单位电量的花费\(P\),求整个旅途的最少花费。
如果\(Jim\)无法保证全程手电筒都亮着输出\(-1\)

Input

\(1\)行: \(2\)个数\(N\),\(T\)中间用空格分隔,\(N+1\)为充电站的数量,\(T\)为手电筒的电池容量\((2≤N≤500000,1≤T≤10^9)\)
\(2\)\(N+1\)行:每行\(2\)个数\(D[i]\),\(P[i]\),中间用空格分隔,分别表示到下一个充电站的距离和充电的单价\((1≤D[i], P[i]≤1000000)\)

Output

输出走完整个旅程的最小花费,如果无法保证手电筒全程照亮,输出\(-1\)

Sample Input

3 15
10 2
9 1
8 3

Sample Output

41

Data Constraint

对于\(30\)%的数据\(N<=50\)
对于\(100\)%的数据\(N<=500000\)

Limit

\(1000ms\) \(256MB\)

Solution

贪心,贪心思路是如果在电量T范围,能够到下一个比当前充电便宜的地方(next),就充到刚好到下一个地方的所需的电。
否则就充满电,到下一个点继续判断。
对于每个点的next,可以O(n)的单调栈预处理。

Code

#include<iostream>
#include<cstdio>
#define ll long long
#define N 500007
using namespace std;
ll ans, n, t, w, rest, now;
ll d[N], p[N], pre[N], nxt[N], q[N];
inline ll read() {
	ll s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 3) + (s << 1) + (c ^ 48);
	return (s * w);
}
int main() {
	freopen("wayhome.in","r",stdin);
	freopen("wayhome.out","w",stdout);
	n = read(), t = read();
	for (register int i = 1; i <= n; i++) {
		d[i] = read(), p[i] = read();
		pre[i] = pre[i - 1] + d[i];
		if (d[i] > t) {
			printf("-1\n"); return 0;
		}
	}
	for (register int i = n; i; i--) {
		while (w && p[q[w]] > p[i]) w--;
		nxt[i] = q[w];
		q[++w] = i;
		if (!nxt[i]) nxt[i] = n + 1;
	}
	for (register int i = 1; i <= n; i++) {
		rest = rest - d[i - 1];
		now = min(pre[nxt[i] - 1] - pre[i - 1], t);
		if (now > rest) ans = ans + (now - rest) * p[i], rest = now;
	}
	printf("%lld", ans);
	return 0;
}
posted @ 2019-11-03 21:36  Agakiss  阅读(265)  评论(0编辑  收藏  举报