二分+贪心 Codeforces614D Skills

来源:互联网 发布:mac server如何使用 编辑:程序博客网 时间:2024/06/06 17:49

传送门:点击打开链接

题意:n个科目,每个科目最高分为A,现在最多能提高m分。最后权值是两种分数算法之和,第一种算法是达到A分的科目个数*cf,第二种算法是最低分*cm。求提高单科分数之后,最后的权值最大是多少。并打印出方案。

思路:枚举达到A分的科目数,然后再二分得到剩下的钱,让最低分最大是多少。

首先,肯定要把科目的所有分数排序一次,然后枚举达到满分的科目时,肯定是从大到小去枚举的。

然后再看剩下的钱数,去二分m,m表示最低分最大是多少。那么问题在check上,然后处理好check就行了~

#include<map>#include<set>#include<cmath>#include<ctime>#include<stack>#include<queue>#include<cstdio>#include<cctype>#include<string>#include<vector>#include<cstring>#include<iomanip>#include<iostream>#include<algorithm>#include<functional>#define fuck(x) cout<<"["<<x<<"]"#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w+",stdout)using namespace std;typedef long long LL;typedef pair<int, int>PII;const int MX = 1e5 + 5;const int mod = 1e9 + 7;const int INF = 0x3f3f3f3f;PII A[MX];int W, cf, cm, n, prt[MX];LL m, sum[MX];bool check(LL m, int x, int p) {    p = min(upper_bound(A + 1, A + 1 + n, PII(x, W)) - A - 1, p - 1);    LL tot = (LL)p * x - sum[p];    return tot <= m;}int get(LL money, int p) {    int l = 1, r = W, m;    if(!check(money, l, p)) return 0;    while(l <= r) {        m = (l + r) >> 1;        if(check(money, m, p)) l = m + 1;        else r = m - 1;    }    return l - 1;}int main() {    //FIN;    while(~scanf("%d%d%d%d%I64d", &n, &W, &cf, &cm, &m)) {        sum[0] = 0;        for(int i = 1; i <= n; i++) {            scanf("%d", &A[i].first);            A[i].second = i;        }        sort(A + 1, A + 1 + n);        for(int i = 1; i <= n; i++) {            sum[i] = sum[i - 1] + A[i].first;        }        int ansa = 0, ansb = get(m, n + 1);        LL s = m, ans = (LL)ansb * cm;        for(int i = n, j = 1; i >= 1; i--, j++) {            s -= W - A[i].first;            if(s < 0) break;            int t = get(s, i);            LL temp = (LL)j * cf + (LL)t * cm;            if(temp > ans) {                ans = temp; ansa = j; ansb = t;            }        }        printf("%I64d\n", ans);        for(int i = n, j = 1; i >= 1; i--, j++) {            if(j <= ansa) prt[A[i].second] = W;            else prt[A[i].second] = max(A[i].first, ansb);        }        for(int i = 1; i <= n; i++) {            printf("%d%c", prt[i], i == n ? '\n' : ' ');        }    }    return 0;}


0 0