CF1415E New Game Plus! 题解
题意:
你有 $n$ 个数 $c_{1 \cdots n}$ 和 $1$ 个初始为 $0$ 的计数器
boss bonus
。你可以任意选择一个尚未被选择过的 $c_{i}$,把
boss bonus
加上 $c_{i}$。你也有 $k$ 次机会把
boss bonus
变成 $0$。每次「选择数字前的
boss bonus
的和」记为你的收获。求收获的最大值。注意 $c_{i}$ 和最后的收获可以为负数。
输入格式:
输入的第一行两个整数,分别是 $n,k$。
输入的第二行 $n$ 个整数,表示 $c_{1 \cdots n}$。
输出格式:
输出一行,最大收获。
数据范围:
$1 \leq n \leq 5 \times 10^5,0 \leq k \leq 5 \times 10^5,-1 \times 10^6 \leq c_{i} \leq 1 \times 10^6$
容易发现,这 $k$ 次机会,其实把 $c$ 就是分成了 $k+1$ 个集合。
每个集合的元素都有不上升的性质,否则一定存在一个集合使得这个元素放进去以后答案增大。
因此我们可以维护一个堆,记录这 $k+1$ 个集合,每次取出值最大的那个堆,往里面塞当前最大的 $c_i$ 。
时间复杂度 $\mathcal{O}(n \log n)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e6 + 16))
int res,a[N];
priority_queue<int> q;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
int n, k; cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n, greater<int>());
for(int i = 1; i <= k + 1; i++) q.push(0);
for(int i = 1; i <= n; i++)
{
int sum = q.top(); q.pop();
res += sum; sum += a[i]; q.push(sum);
}
cout << res << '\n';
return 0;
}
参考文献: