Codeforces Round #339 D. Skills

                                                             D. Skills
                                                   time limit per test
                                                          2 seconds
                                               memory limit per test
                                                    256 megabytes
 

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 exactlyn skills. Each skill is represented by a non-negative integerai — the current skill level. All skills have the same maximum levelA.

Along with the skills, global ranking of all players was added. Players are ranked according to the so-called Force. TheForce 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 coefficientcf.
  • The minimum skill level among all skills (min ai), multiplied by coefficientcm.

Now Lesha has m hacknetian currency units, which he is willing to spend. Each currency unit can increase the current level of any skill by1 (if it's not equal toA yet). Help him spend his money in order to achieve the maximum possible value of the Force.

Input

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 integersai (0 ≤ ai ≤ A), separated by spaces, — the current levels of skills.

Output

On the first line print the maximum value of the Force that the character can achieve using no more thanm 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.


Examples

Input
3 5 10 1 5
1 3 1
Output
12
2 5 2 

Input
3 5 10 1 339
1 3 1
Output
35
5 5 5 

Note

In the first test the optimal strategy is to increase the second skill to its maximum, and increase the two others by1.

In the second test one should increase all skills to maximum.






//总体思路:  暴力加二分,

//枚举[i+1,n]技能都被升到顶级了, [0,i]维护一个尽可能大的最低技能等级

#include
using namespace std;

typedef long long llint;
const int maxn = 1e5 + 100;
struct Node {
    llint val;
    int pos;
} a[maxn];
llint dp[maxn];
llint A, fmaxx, fminn, m;
int n;

int cmp1(Node aa, Node bb) {
    return aa.val < bb.val;
}

int cmp2(Node aa, Node bb) {
    return aa.pos < bb.pos;
}

llint solve(llint mm, int start) { //二分搜索剩下的mm值可以填充的最大的最小值
      if(start == 0)
        return A;  //这里非常重要, 想想为什么,  测试数据 6 就是这个  1 100 1 2 30  71;
      int l = 0, r = start - 1;
      int mid;
      while(l < r){
        mid = (l + r + 1) / 2;   //由于是取左边界, 故。。。
        llint need =(llint) dp[mid] - (A - a[mid].val) * (mid + 1); // 填充到mid ,所需要的话费
        if(need < mm){
            l = mid;
        }else{
            r = mid - 1;
        }
      }
      llint need =(llint) dp[l] - (A - a[l].val) * (l + 1); //需要的花费
      llint ans =(llint) a[l].val + (mm - need) / (l + 1);
      return min(A, ans);;

}

int  main() {
    //freopen("in.txt", "r", stdin);
    scanf("%d %I64d %I64d %I64d %I64d", &n, &A, &fmaxx, &fminn, &m);

    //由于输出需要原始序列, 故用结构体保存;
    for(int i = 0; i < n; i++) {
        scanf("%I64d", &a[i].val);
        a[i].pos = i;
    }
    //按照输入的值的大小排序;
    sort(a, a + n, cmp1);

    //dp[I] 表示使0 - i 都保存到A需要多少钱;
    for(int i = 0; i < n; i++) {
        if(i == 0) {
            dp[i] = A - a[i].val;
        } else {
            dp[i] = dp[i-1] + A - a[i].val;
        }
    }

    llint ans_number = -1;   //升级之后最大的最小值;
    llint ans_pos = -1;      //升级之后第一个填充满的位置
    llint ans = -1;          //最后的值
    llint mm = m;
    a[n].val = A;            //这里是为了,当一个都不填充满的时候。
    for(int i = n - 1; i>=-1; i--){
        mm -= (A - a[i+1].val);   //剩下的 mm 值
        if(mm < 0)                //如果小与 0 就退出,  等于0的时候还需要查找最小的值, 故不退出!
            break;
        llint tem_x = solve(mm, i+1); //填充后序列中最小值
        llint tem_p = tem_x * fminn + (n - i - 1) * fmaxx;  //两个部分相加
        if(tem_p > ans){                  // 如果大于, 就更新值
            ans = tem_p;
            ans_number = tem_x;
            ans_pos = i + 1;
        }
    }
    // 小与平均值的都更新为平均值
    for(int i = 0; i < n; i++){
       a[i].val = max(a[i].val, ans_number);
    }
    //填充满的更新为A的值
    for(int i = ans_pos; i 





你可能感兴趣的:(ACM)