【Codeforces Round 339 (Div 2)D】【暴力 贪心 二分】Skills 最高技能人数乘cm+最低技能乘cf权值最大

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

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.

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 integers ai (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 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.

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 by 1.

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


#include<stdio.h> 
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int n; LL m;
int A; LL cf, cm;
LL sum[N];
struct Skill
{
	int v, o;
}a[N];
bool cmp1(Skill a, Skill b)
{
	return a.v < b.v;
}
bool cmp2(Skill a, Skill b)
{
	return a.o < b.o;
}
int solve(int R, LL now)
{
	if (R == 0)return A;
	int l = 1;
	int r = R;
	while (l < r)
	{
		int mid = (l + r + 1) >> 1;
		LL need = (LL)a[mid].v * mid - sum[mid];//还需要花费这么多才能达到第mid个人的水平
		if (need > now)r = mid - 1;
		else l = mid;
	}
	LL need = (LL)a[l].v*l - sum[l];
	LL more = (now - need) / l;
	return min((LL)A, a[l].v + more);
}
int main()
{
	while (~scanf("%d%d%lld%lld%lld", &n, &A, &cf, &cm, &m))
	{
		//第一步:排序,使得技能等级严格升序,因为输出格式需要,我们还要对应到每个技能的编号
		for (int i = 1; i <= n; ++i) { scanf("%d", &a[i].v); a[i].o = i; }
		sort(a + 1, a + n + 1, cmp1); a[n + 1].v = A;

		//第二部:维护技能等级之和的前缀和,用于后来快速计算可提升等级
		for (int i = 1; i <= n; ++i)sum[i] = sum[i - 1] + a[i].v;

		//第三步,枚举我们使得多少人的技能加满
		LL ans = -1;
		LL cost = 0;
		int v, p;
		//枚举[i+1,n]技能都被我们升到顶级了,[1,i]被我们维护一个尽可能大的最低技能等级
		for (int i = n; i >= 0; --i)
		{
			cost += A - a[i + 1].v;
			if (cost > m)break;
			int minv = solve(i, m - cost);
			LL tmp = minv*cm + (n - i)*cf;
			if (tmp > ans)
			{
				ans = tmp;
				p = i;
				v = minv;
			}
		}

		printf("%lld\n", ans);
		for (int i = n; i > p; --i)a[i].v = A;
		for (int i = 1; i <= p; ++i)gmax(a[i].v, v);
		sort(a + 1, a + n + 1, cmp2);
		for (int i = 1; i <= n; ++i)printf("%d ", a[i].v); puts("");
	}
	return 0;
}
/*
【trick&&吐槽】
1,比赛的时候一定要专注,一定要注意程序的细节以及代码的条理性。
这么水的题我竟然晚16sAC >_< 蠢炸了。
2,做题之前一定要注意要输出的格式,否则可能写完了还要为了输出调整程序。
3,一些很容易爆int的题,干脆就全用LL吧>_<

【题意】
每个人有n(1e5)个技能,技能等级都在[0,1e9]范围
每个技能有一个当前等级,所有技能的最高等级都为A

一个人的力量被记做以下两项的和
1,顶级技能的个数*cf
2,最低等级的技能*cm

我们希望花尽可能小的钱,使得力量尽可能高

【类型】
暴力 二分

【分析】
根据能力计算方式,显然,我们在意的是顶级技能的个数和低级技能的个数。
我们枚举顶级技能的个数,二分出我们能提升的底级技能的个数。

需要记录——
1,到达i个顶级技能需要花费的钱数
2,使得低级技能为x

【时间复杂度&&优化】
3 5 10 1 0
1 3 1
*/


你可能感兴趣的:(codeforces,贪心,二分,暴力,题库-CF)