Skills CodeForces

来源:互联网 发布:青岛seo网络优化 编辑:程序博客网 时间:2024/05/20 01:11

题目链接: Skills CodeForces - 614D

大意

有n项技能, 每项技能的等级为ai, 技能最大等级为A, =Acf+minaaicm
现在有m个技能点(一个技能点可以将一个技能升一级, 达到A后就不能再升了), 求能达到的最大能力值

思路

二分
想要提升能力值, 有两种手段, 增加等级为A的技能数量, 让最小值增大
如果我们枚举等级为A的技能的数量(使用技能点提升后), 还剩下x技能点, 接下来就要用这x个技能点使最小值最大化, 二分
先将技能按等级从小到大排序, 然后求前缀和
那么等级为A的技能数量变成i, 所消耗的技能点=i*A - (sum[n]-sum[n-i])
那么剩下的技能点x = m- 已经消耗的
然后在[0, A]范围内二分, 求出最大最小值
二分中check方法是再用一个二分(这里直接用lower_bound)求出技能等级小于mid的数量, 然后和上面计算一样利用sum计算出需要技能点

代码

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 1e5+100;ll n, A, cf, cm, m, sum[maxn];struct P{    ll a, id;    P(ll x, ll y) :a(x), id(y){};    P(){}    bool operator<(const P &x) {return a < x.a;}}p[maxn];int main(){    cin >> n >> A >> cf >> cm >> m;    for(int i=0; i<n; ++i)    {        scanf("%I64d", &p[i].a);        p[i].id = i;    }    sort(p, p+n);    for(int i=0; i<n; ++i) sum[i+1] = sum[i]+p[i].a;    int tcnt = 0;    for(int i=0; i<n; ++i) if(p[i].a == A) ++tcnt;    ll ans = tcnt*cf + p[0].a*cm;    int cntm = 0;    int mi = 0;    for(int i=0; i<=n; ++i)    {        ll x = m - (A*i-(sum[n]-sum[n-i]));        if(x<=0) break;        ll l=0, r=A, mid;        while(l<r)        {            mid = (l+r)/2;            int cnt = lower_bound(p, p+n-i, P(mid, 0ll)) - p;            if(cnt*mid-sum[cnt] <= x) l = mid+1;            else r = mid;        }        int tcnt = lower_bound(p, p+n-i, P(l, 0ll))-p;        if(tcnt*l-sum[tcnt] > x) --l;        ll tans = i*cf + l*cm;        if(tans > ans)        {            ans = tans;            cntm = i;            mi = l;        }    }    for(int i=n-1; i>=0 && cntm; --i, --cntm) p[i].a = A;    for(int i=0; i<n; ++i) if(p[i].a < mi) p[i].a = mi;    sort(p, p+n, [](const P&x, P&y) {return x.id < y.id; });    cout << ans << endl;    for(int i=0; i<n; ++i) printf("%I64d ", p[i].a);    cout <<endl;    return 0;}