CF1355E Solution

题目链接

题解

如果(M>A+R)的话(可能还要加上些奇奇怪怪的条件,总之就是全部弄成(M)最优的情况),把高度变为平均数一定最优,这样可以最大化使用(M)。如果(M)没有太大用处,而是要在(A,R)之间找平衡的话,可以发现最终高度一定为某个柱子的高度。简单证明:将(h)数组升序排序,设(h_i<res<h_{i+1})(res)为最终高度)。若(A>R),将(res)调至(h_i)可以使花费减少(icdot (res-h_i)cdot (A-R));若(A<R),将(res)调至(h_{i+1})可以使花费减少((n-i)cdot (h_{i+1}-res)cdot (R-A));若(A=R),则等于多少都无所谓。

因此求出取平均数时的花费与取每个柱子时的花费就可以啦,时间复杂度(O(n))

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int h[N],sum[N],n,a,r,m;
int sol(int x,int op)
{
	int pos;
	if(!op) pos=lower_bound(h+1,h+n+1,x)-h-1;//其实不需要二分
	else pos=op;
	int qwq=min(pos*x-sum[pos],sum[n]-sum[pos]-(n-pos)*x);
	return qwq*m+(pos*x-sum[pos]-qwq)*a+(sum[n]-sum[pos]-(n-pos)*x-qwq)*r;
}
signed main()
{
	scanf("%lld%lld%lld%lld",&n,&a,&r,&m); m=min(a+r,m);
	for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
	sort(h+1,h+n+1);
	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+h[i];
	int ans=min(sol(sum[n]/n,0),sol(sum[n]/n+1,0));//平均数可能是小数,上下取整都试一下
	for(int i=1;i<=n;i++) ans=min(ans,sol(h[i],i));
	printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/violetholmes/p/14633750.html