Codeforces614D Skills
题意:n个科目,每个科目最高分为A,现在最多能提高m分。最后权值是两种分数算法之和,第一种算法是达到A分的科目个数*cf,第二种算法是最低分*cm。求提高分数之后,最后的权值最大是多少。并打印出方案。
题解:最大值有x个,最小值为y,那么权值就是w = cf*x+cm*y可以发现这里有两个变量,考虑枚举一个,二分另外一个
#include <bits/stdc++.h> #define maxn 100010 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; ll n, A, cf, cm, m, t1, t2; pair<ll, ll >a[maxn]; ll sum[maxn], ma; ll cmp(pair<ll, ll >aa, pair<ll, ll >bb){ return aa.second<bb.second; } ll f(ll x, ll r){ ll l = 1, pos = -1; while(l<=r){ ll mid = (l+r)>>1; if(a[mid].first <= x) l = mid+1, pos = mid; else r = mid-1; } return x*pos-(sum[pos]-sum[0]); } int main(){ scanf("%lld%lld%lld%lld%lld", &n, &A, &cf, &cm, &m); for(ll i=1;i<=n;i++) scanf("%lld", &a[i].first), a[i].second = i; sort(a+1, a+n+1); for(ll i=1;i<=n;i++) sum[i] = sum[i-1]+a[i].first; for(ll i=0;i<=n;i++){ ll t = m-(A*i-sum[n]+sum[n-i]); if(t < 0) break; ll l=1,r=A,mi=-1; while(l<=r){ ll mid = (l+r)>>1; if(f(mid,n-i) <= t) l = mid+1, mi = mid; else r = mid-1; } ll temp = mi*cm+cf*i; if(ma < temp){ ma = temp; t1 = i; t2 = mi; } } for(ll i=1;i<=n;i++){ if(a[i].first < t2) a[i].first = t2; if(n-i+1 <= t1) a[i].first = A; } sort(a+1, a+1+n, cmp); printf("%lld\n", ma); for(ll i=1;i<=n;i++) printf("%lld ", a[i].first); return 0; }
posted on 2018-03-27 20:48 2855669158 阅读(119) 评论(0) 编辑 收藏 举报