题解:CF2085D Serval and Kaitenzushi Buffet
Part1:思路
这题虽然简单,但是反应的思维方式比较有意义。
首先,去刻画什么情况下一盘寿司能被选择——显然是后面至少有
这里的关键在于后面,但是后面的情况如何正着做是不知道的。换句话说,前面数的选择与否只与后面的情况有关,所以我们从后往前考虑。
遇到这种选择物品题,我们往往第一反应都会是贪心。从后往前扫的时候,假若现在是第
但是这里显然不满足最优子结构。考虑刻画非最优的情况。具体的,对于第
更加广泛的,对于任意
Part2:代码
#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;
}