专栏文章

题解:CF2085D Serval and Kaitenzushi Buffet

CF2085D题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mipq2diw
此快照首次捕获于
2025/12/03 16:05
3 个月前
此快照最后确认于
2025/12/03 16:05
3 个月前
查看原文

Part1:思路

这题虽然简单,但是反应的思维方式比较有意义。
首先,去刻画什么情况下一盘寿司能被选择——显然是后面至少有 kk 分钟空着没事做。
这里的关键在于后面,但是后面的情况如何正着做是不知道的。换句话说,前面数的选择与否只与后面的情况有关,所以我们从后往前考虑。
遇到这种选择物品题,我们往往第一反应都会是贪心。从后往前扫的时候,假若现在是第 nkn-k 分钟,那么后面恰好有 kk 分钟空余,我们将选择当前这盘寿司。
但是这里显然不满足最优子结构。考虑刻画非最优的情况。具体的,对于第 1nk11\sim n-k-1 中任意一盘没选中的寿司,假若选择它会带来更大美味值,那么我们都可以使用后面的寿司替换第 nkn-k 盘。
更加广泛的,对于任意 j<ij<i,我们都可以使用第 jj 盘寿司替换第 ii 盘。这时候就得到了一个反悔贪心,对于其正确性此时再稍作归纳便可得知。

Part2:代码

CPP
#include <bits/stdc++.h>
#define FL(i, a, b) for (int i = (a); i <= (b); ++i)
#define FR(i, a, b) for (int i = (a); i >= (b); --i)
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define Sz(v) ((int)(v).size())
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
constexpr int N = 2e5 + 10;
int n, k, d[N];
multiset<int> s1;
void Solve() {
    scanf("%d %d", &n, &k);
    FL(i, 1, n) {
        scanf("%d", &d[i]);
    }
    s1.clear();
    ll ans = 0;
    FR(i, n, 1) {
        int lim = (n - i + 1) / (k + 1);
        if (Sz(s1) < lim) {
            ans += d[i];
            s1.emplace(d[i]);
        } else {
            if (!s1.empty() && *s1.begin() < d[i]) {
                ans -= *s1.begin();
                s1.erase(s1.begin());
                ans += d[i];
                s1.emplace(d[i]);
            }
        }
    }
    printf("%lld\n", ans);
}
int main() {
    int T = 1;
    scanf("%d", &T);
    for (; T--; Solve());
    return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...