【Codeforces613B】Skills【二分】【枚举】【贪心】

来源:互联网 发布:java树形结构简单实现 编辑:程序博客网 时间:2024/05/17 08:31

http://codeforces.com/problemset/problem/613/B

题意:

有n个数,可以将其中一个数字加一,最多操作m次。给出最大值A,给出cf,cm。设等于A的数的个数为k,最小值为min,那么答案为k * cf + min * cm。求最大的答案,并输出最后的n个数。


排序,从大的一端枚举将多少数变为A,二分最小值,然后在小的一端二分查找可以使多少数变为最小值,更新答案。


懵逼,二分写搓了真容易被卡。


/* Footprints In The Blood Soaked Snow */#include <cstdio>#include <utility>#include <algorithm>using namespace std;typedef long long LL;typedef pair<int, int> pii;const int maxn = 100005;int n, A, cf, cm, val[maxn];LL m, sum[maxn];pii num[maxn];inline bool check(int x, LL left, int mr) {int l = 1, r = mr;while(l <= r) {int mid = l + r >> 1;if(num[mid].first <= x) l = mid + 1;else r = mid - 1;}return (LL)r * x - sum[r] <= left;}int main() {scanf("%d%d%d%d%I64d", &n, &A, &cf, &cm, &m);for(int i = 1; i <= n; i++) {scanf("%d", &num[i].first);num[i].second = i;}sort(num + 1, num + 1 + n);for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + num[i].first;LL ans = -1, maxtot = 0, minval = 0;for(int i = 0; i <= n; i++) {LL left = m - ((LL)i * A - (sum[n] - sum[n - i]));if(left < 0) break;int l = 0, r = A;while(l <= r) {int mid = l + r >> 1;if(check(mid, left, n - i)) l = mid + 1;else r = mid - 1;}LL res = (LL)i * cf + (LL)r * cm;if(res > ans) {ans = res;maxtot = i;minval = r;}}for(int i = 1; i <= n; i++)if(n - maxtot < i) val[num[i].second] = A;else if(num[i].first <= minval) val[num[i].second] = minval;else val[num[i].second] = num[i].first;printf("%I64d\n", ans);for(int i = 1; i <= n; i++) printf("%d ", val[i]);return 0;}


0 0
原创粉丝点击