[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;
}
只要有想见的人,就不是孤身一人了。