題意:給出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();}
}