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