CF1415E New Game Plus! 题解
题意:
你有 n 个数 c1⋯n 和 1 个初始为 0 的计数器
boss bonus
。你可以任意选择一个尚未被选择过的 ci,把
boss bonus
加上 ci。你也有 k 次机会把
boss bonus
变成 0。每次「选择数字前的
boss bonus
的和」记为你的收获。求收获的最大值。注意 ci 和最后的收获可以为负数。
输入格式:
输入的第一行两个整数,分别是 n,k。
输入的第二行 n 个整数,表示 c1⋯n。
输出格式:
输出一行,最大收获。
数据范围:
1≤n≤5×105,0≤k≤5×105,−1×106≤ci≤1×106
容易发现,这 k 次机会,其实把 c 就是分成了 k+1 个集合。
每个集合的元素都有不上升的性质,否则一定存在一个集合使得这个元素放进去以后答案增大。
因此我们可以维护一个堆,记录这 k+1 个集合,每次取出值最大的那个堆,往里面塞当前最大的 ci 。
时间复杂度 O(nlogn)
代码:
cpp
#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;
}
参考文献: