题解 CF2207B 【One Night At Freddy's】
我方的策略是显然的:每次闪光时选取一个最大的
有鉴于此,除非
那么对方一定会将最小的
推而广之,可得如下贪心算法:
- (1) 对方:在时刻
i ,若我方后续还有j 次闪光机会,则考虑当前前j + 1 大的d_k 。 - 将这些
d_k 中最小者加1 。 - (2) 我方:在时刻
a_i ,选取当前最大的d_i 并将其置为0 。
用一个 set 模拟即可。时间复杂度为
代码:
#include <iostream>
#include <set>
#include <cstdio>
using namespace std;
int a[200001];
multiset<int> s;
void solve(){
int n, m, l;
scanf("%d %d %d", &n, &m, &l);
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
s.clear();
for (int i = 1; i <= m; i++){
s.insert(0);
}
for (int i = 1; i <= n; i++){
while (s.size() > n - i + 2) s.erase(s.begin());
for (int j = a[i - 1] + 1; j <= a[i]; j++){
int mind = *s.begin();
s.erase(s.begin());
s.insert(mind + 1);
}
s.erase(--s.end());
s.insert(0);
}
cout << *(--s.end()) + (l - a[n]) << endl;
}
int main(){
int t;
scanf("%d", &t);
for (int cas = 1; cas <= t; cas++){
solve();
}
return 0;
}