CF 1430F Realistic Gameplay

题目描述

https://codeforces.com/contest/1430/problem/F

Solution

容易发现在能完成任务的情况下,如果可以不换弹夹就一定不换(最后一个弹夹不算的情况下显然

另外我们注意到对于一波来说,我们可以更新弹夹的时间是 $[l+1,r]$,所以一共能换 $r-l$ 次弹夹

那么对于一波我们还需要知道的信息就是在 $l$ 时我们有多少子弹

由于两波之间在端点处可能重叠,所以我们考虑倒着算出每波开始前至少要多少子弹

然后正着贪心即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#define maxn 2010
#define ll long long
#define pb push_back
#define INF 10000000000000000ll
using namespace std;

int n; ll m;

struct node {
int l, r, v;
} a[maxn];

ll f[maxn];
int main() {
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> a[i].l >> a[i].r >> a[i].v;
for (int i = n; i; --i) {
if (a[i].r == a[i + 1].l) f[i] = max(0ll, a[i].v + f[i + 1] - (a[i].r - a[i].l) * m);
else f[i] = max(0ll, a[i].v - (a[i].r - a[i].l) * m);
if (f[i] > m) return puts("-1"), 0;
}
ll ans = 0, tp = m;
for (int i = 1; i <= n; ++i) {
if (tp < f[i]) ans += tp, tp = m;
ans += a[i].v;
if (a[i].v >= tp) tp = m - (a[i].v - tp) % m;
else tp -= a[i].v;
} cout << ans << endl;
return 0;
}