Educational Codeforces Round 96 (Rated for Div. 2) F. Realistic Gameplay

思路:如果不存在 (le[i]==r[i + 1]) 的情况,这题 (for) 一遍就好了,当存在 (le[i]==r[i + 1]) 的情况时,我们没有时间更换弹夹就会开始下一波,所以我们要求出在每一波开始时弹匣里子弹最少所需的容量 (dp[i]) ,由于可能存在连续的 (le[i]==r[i + 1]) 的情况,所以我们从后往前遍历,求出 (dp[i]) ,然后如果碰到不可能的情况直接输出 (-1) 结束,然后正着遍历一遍就可以解决了。

#include <bits/stdc++.h>
using namespace std;
#define lc (rt << 1)
#define rc ((rt << 1) | 1)
#define fi first
#define se second
#define pb push_back
#define pii pair<int, int>
#define rep(i, l, r) for (int i = (l); i <= (r); ++i)
#define per(i, r, l) for (int i = (r); i >= (l); --i)
#define PE(i, u) for (int i = head[u]; i != -1; i = edge[i].next)
typedef long long LL;
const int maxn = 1e6 + 20;
const int mod = 1e9 + 7;
int n, m;
int le[maxn], ri[maxn], a[maxn], dp[maxn];
int main(int argc, char const *argv[])
{
    scanf("%d%d", &n, &m);
    rep(i, 1, n){
        scanf("%d%d%d", &le[i], &ri[i], &a[i]);
    }
    per(i, n, 1){
        int need = a[i];
        if(i + 1 <= n && ri[i] == le[i + 1]){
            need += dp[i + 1];
        }
        if(need > 1LL * (ri[i] - le[i] + 1) * m){
            printf("-1
");
            return 0;
        }
        dp[i] = max(0LL, need - 1LL * (ri[i] - le[i]) * m);
    }
    LL ans = 0;
    int lim = m;
    rep(i, 1, n){
        if(lim < dp[i]){
            ans += lim;
            lim = m;
        }
        ans += a[i];
        if(lim > a[i]) lim -= a[i];
        else lim = m - (a[i] - lim) % m;
    }
    printf("%I64d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/PCCCCC/p/13822667.html