【补题】Codeforces Round 664 (Div. 1) A. Boboniu Chats with Du
题意:给出n,d,m三个值,分别代表,有多少个值ai,使用超过m的ai,需要禁言d天,如果不足也能使用,m代表区分点,问能得到最大的值有多少。
思路: CF1394A Boboniu Chats with Du - 洛谷
1.很容易想到的一个点就是能用大值越多越好,同时因为天数不足也是可以选取的,所以大值在时间轴上的顺序,越靠后越好。
2.最简单的答案就是我就选小值,也不用讨论禁言了,然后考虑开始放入大值,那么一定是放在当前时间轴的最后,因为区分点的缘故,先分开值之间的区别,对于两堆的贪心,均是能用越大的越好。所以考虑枚举,每添加一个大值,优先使用剩下不用的大值去抵消天数,如果不够在用小值。
利用前缀和O(1)返回剩余小值的贡献,O(n)累加枚举大值即可
代码:
#include <bits/stdc++.h>
#define int long long
#define int128 __int128
#define IOS \std::ios::sync_with_stdio(0); \std::cin.tie(0); \std::cout.tie(0);
const int N = 1e6 + 10;
const int INF = 1e18;
const int MOD = 998244353;void solve() {int n, d, m;std::cin >> n >> d >> m;std::vector<int> sm;std::vector<int> bi;for(int i = 0; i < n; i++) {int x;std::cin >> x;if(x <= m) {sm.push_back(x);} else {bi.push_back(x);}}sort(sm.begin(), sm.end(), std::greater());sm.insert(sm.begin(), 0);sort(bi.begin(), bi.end(), std::greater());int sum = 0;for(int i = 1; i < sm.size(); i++) {sm[i] = sm[i - 1] + sm[i];}int res = sm[sm.size() - 1];for(int i = 0; i < bi.size() && i * d + (i + 1) <= n; i++) {sum += bi[i];int mini = std::min(n - (i * d + (i + 1)), (int)sm.size() - 1);// std::cout << sm[mini] << " " << sum << '\n';res = std::max(res, sum + sm[mini]);// std::cout << sm[sm.size() - 1 - i * d] << " " << sum << "\n";}std::cout << res << '\n';
}signed main() {IOS;int t = 1;// std::cin >> t;while(t--) {solve();}
}