codeforces 613B B. Skills(枚举+二分+贪心)
题目链接:
Lesha plays the recently published new version of the legendary game hacknet. In this version character skill mechanism was introduced. Now, each player character has exactly n skills. Each skill is represented by a non-negative integer ai — the current skill level. All skills have the same maximum level A.
Along with the skills, global ranking of all players was added. Players are ranked according to the so-called Force. The Force of a player is the sum of the following values:
- The number of skills that a character has perfected (i.e., such that ai = A), multiplied by coefficient cf.
- The minimum skill level among all skills (min ai), multiplied by coefficient cm.
Now Lesha has m hacknetian currency units, which he is willing to spend. Each currency unit can increase the current level of any skill by 1 (if it's not equal to A yet). Help him spend his money in order to achieve the maximum possible value of the Force.
The first line of the input contains five space-separated integers n, A, cf, cm and m (1 ≤ n ≤ 100 000, 1 ≤ A ≤ 109, 0 ≤ cf, cm ≤ 1000,0 ≤ m ≤ 1015).
The second line contains exactly n integers ai (0 ≤ ai ≤ A), separated by spaces, — the current levels of skills.
On the first line print the maximum value of the Force that the character can achieve using no more than m currency units.
On the second line print n integers a'i (ai ≤ a'i ≤ A), skill levels which one must achieve in order to reach the specified value of the Force, while using no more than m currency units. Numbers should be separated by spaces.
3 5 10 1 5
1 3 1
12
2 5 2
3 5 10 1 339
1 3 1
35
5 5 5
题意:
m次操作,每次可以任选一个a[i]++,最后要求min(a[i])*cm+num(a[i]==A)*cf最大;
思路:
先排序,再枚举a[i]==A的个数,然后二分min(a[i]),根据贪心的原则,要使num尽量多,那么应该从最大的a[i]开始变成A,要使min(a[i])尽可能大,那么应该把最小的++;
AC代码:
//#include <bits/stdc++.h> #include <vector> #include <iostream> #include <queue> #include <cmath> #include <map> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; #define Riep(n) for(int i=1;i<=n;i++) #define Riop(n) for(int i=0;i<n;i++) #define Rjep(n) for(int j=1;j<=n;j++) #define Rjop(n) for(int j=0;j<n;j++) #define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; template<class T> void read(T&num) { char CH; bool F=false; for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar()); for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar()); F && (num=-num); } int stk[70], tp; template<class T> inline void print(T p) { if(!p) { puts("0"); return; } while(p) stk[++ tp] = p%10, p/=10; while(tp) putchar(stk[tp--] + '0'); putchar('\n'); } const LL mod=1e9+7; const double PI=acos(-1.0); const LL inf=1e14; const int N=1e5+15; int n,cf,cm; LL m,pre[N],nex[N],A; struct node { int a,id; }po[N]; int cmp(node x,node y) { return x.a<y.a; } int cmp1(node x,node y) { return x.id<y.id; } int check(LL y,LL x,int fr) { int l=1,r=fr; while(l<=r) { int mid=(l+r)>>1; if(po[mid].a<=x)l=mid+1; else r=mid-1; } if(y>=x*(l-1)-pre[l-1])return 1; return 0; } int fipos,fnum; int tpos,tnum; LL solve(int x) { int num=n+1-x; if(m>=num*A-nex[x]) { LL temp=m-num*A+nex[x]; LL l=po[1].a,r=A; while(l<=r) { LL mid=(l+r)>>1; if(check(temp,mid,x-1))l=mid+1; else r=mid-1; } tpos=(int)(l-1),tnum=num; return (l-1)*cm+num*cf; } return 0; } int main() { read(n);read(A);read(cf);read(cm);read(m); Riep(n)read(po[i].a),po[i].id=i; sort(po+1,po+n+1,cmp); pre[0]=0;nex[n+1]=0; for(int i=1;i<=n;i++)pre[i]=pre[i-1]+po[i].a; for(int i=n;i>0;i--)nex[i]=nex[i+1]+po[i].a; int pos=0; LL ans=0; for(int i=n+1;i>0;i--) { LL d=solve(i); if(d>ans) { ans=d; pos=i; fipos=tpos; fnum=tnum; } } cout<<ans<<"\n"; for(int i=n;i>n-fnum;i--) { po[i].a=(int)A; } for(int i=1;i<=n;i++) { if(po[i].a<fipos)po[i].a=fipos; } sort(po+1,po+n+1,cmp1); Riep(n)printf("%d ",po[i].a); return 0; }