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
In the first test the optimal strategy is to increase the second skill to its maximum, and increase the two others by 1.
In the second test one should increase all skills to maximum.
这道题要求解最小值*cm+A的个数*cf的最大值。因为要求解数组的最小值,首先想到排序。按照从小到大排序。并且记录下标。这样要求这个表达式的最大值,越靠近末尾的数字越接近A。但是让数组末尾出现连续的A这样能否保证最优性呢?要让表达式的值最大,我们首先要尽可能把m值用完。当a[i]=A,a[i+1]<A并且在m尽可能用完的情况下,我们让a[i]达到A,花费A-a[i];这样还不如让a[i+1]达到A,此时花费为A-a[i+1]。因为a[i]<=a[i+1],则A-a[i+1]<=A-a[i],a[i+1]要达到A会比a[i]更容易些。这样就满足了贪心的原理。就可以从n向1开始遍历,即让数组末尾达到A的个数不断增加。当然需要注意的第一点就是遍历从n+1到2,从n+1开始相当于没有元素达到A,然后就只需要提高最小值。但是有个地方就是如果此时最小值达到了A,虽然我们假定的是在n+1时,没有元素达到A。这样就矛盾了。所以对最小值还要特殊判断是否为A。这种情况实际上相当于把所有元素都加满到A。也就是m够用,可以把所有数字加到A。然后遍历的下界为2的理由是因为如果遍历到1的话,相当于已经满足了所有的数字都被加满到A。这种情况就重复了,之前处理过,所以就不用考虑。在m足够将k个末尾数字加到A的情况下,在1~n-k的范围内,要找到一个高度h,让1~pos的范围内的数字都相等,且为最小值。也就是把1~pos加满到h。
这个地方开始傻逼了,假设当前位置为i,就天真地觉得1~i-1的sum值加上m剩下的值再除以i-1就是h。后来才发现这特么的必须保证移动这个范围内的数字才可以保证每个数字都为h。所以这个h不能这么求。。。只能在数组最小值min~A的范围内二分枚举。然后找到最合适的位置。
还有一个坑就是一直用int变量,结果很容易在乘法的时候爆掉int。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define CLR(x) memset(x,0,sizeof(x))
#define REP(i,l,r) for(int i=l;i<=r;i++)
#define RREP(i,l,r) for(int i=l;i>=r;i--)
#define _s(x) scanf("%d",&x)
#define _sc(x) scanf("%c",&x)
#define _ss(x) scanf(" %s",x)
#define _sl(x) scanf("%I64d",&x)
#define _sd(x) scanf("%lf",&x)
#define _pt(x) printf("%d",x)
#define _ps(x) printf("%s",x)
#define _pc(x) printf("%c",c)
#define _pl(x) printf("%I64d",x)
#define _pn printf("\n");
#define _p printf(" ");
#define ll long long
using namespace std;
int n,cf,cm;
int a[100010],b[100010],id[100010];
ll A,m,sum[100010];
inline bool cmp(const int& x,const int& y) {
if(a[x]==a[y]) return x<y;
return a[x]<a[y];
}
ll check(ll h,int i){
if(h>b[i]) return h*i-sum[i];
int pos=lower_bound(b+1,b+i+1,h)-b;
if(b[pos]==h){
return h*pos-sum[pos];
}else{
if(pos==1){
return 0;
}else{
return h*(pos-1)-sum[pos-1];
}
}
}
int main() {
while(~scanf("%d%I64d%d%d%I64d",&n,&A,&cf,&cm,&m)) {
sum[0]=0;
REP(i,1,n) {
_s(a[i]);
b[i]=a[i];
id[i]=i;
}
sort(id+1,id+n+1,cmp);
sort(b+1,b+n+1);
REP(i,1,n) {
sum[i]=sum[i-1]+a[id[i]];
}
ll ans=-1;
int ht=0,cr=0;
if(m-(n*A-sum[n])>=0){
ans=n*cf+A*cm;
printf("%I64d\n",ans);
for(int i=1;i<=n;i++)
printf("%d ",A);
printf("\n");
continue;
}
RREP(i,n+1,2) {
ll cnt=(n-i+1)*cf;
ll res=m-((n-i+1)*A-(sum[n]-sum[i-1]));
if(b[i-1]==A) continue;
if(res<0) break;
int l=b[1],r=A;
while(l<r){
int mid=(l+r)>>1;
ll num=check(mid,i-1);
if(num<=res) l=mid+1;
else r=mid-1;
}
while(l>=b[1]&&check(l,i-1)>res) --l;
cnt+=(ll)l*cm;
if(cnt>ans){
ans=cnt;
ht=l,cr=i;
}
}
_pl(ans);_pn;
REP(i,1,n){
if(a[id[i]]<=ht) a[id[i]]=ht;
if(i>=cr) a[id[i]]=A;
}
REP(i,1,n){
_pt(a[i]);_p;
}
_pn;
}
}