比较厉害的一个题目吧
Description
Solution
我们首先发现 (M=min(M,A+R))
然后考虑二分做这个题
二分高度,考虑怎么 (check)
我们发现这个题对于一个已知的高度,怎么求花费呢?
把多于和少于高度 (H) 的砖的数目统计出来,然后这个数乘上 (M) 再加上缺少的乘 (A) 或者是多出来的乘 (R)
这么统计答案,随着给定 (H) 的增加,答案是个单谷的(可以手推一下……)
这个波谷在 (frac {sum} 2) 或者 (frac{sum} 2+1) 中
但是不要忘记把每个砖的高都作为最终高度算一下(防卡)
所以可能就不需要二分了
别忘了先 (sort)
复杂度:(O(nlog n))
(居然复杂度又到了 (sort) 上)
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=1e5+10;
int n,a,r,m,h[N],sum[N],ans=1e15+10;
inline int solve(int x)
{
int pos=lower_bound(h+1,h+n+1,x)-h-1,res=0;
int c1=x*pos-sum[pos],c2=sum[n]-sum[pos]-x*(n-pos);
res=min(c1,c2); c1-=res; c2-=res; res*=m;
res+=c1*a+c2*r;
return res;
}
signed main()
{
n=read(); a=read(); r=read(); m=read();
m=min(m,a+r);
for(int i=1;i<=n;++i) h[i]=read();
sort(h+1,h+n+1);
for(int i=1;i<=n;++i) sum[i]=sum[i-1]+h[i];
ans=min(solve(sum[n]/n+1),solve(sum[n]/n));
for(int i=1;i<=n;++i) ans=min(ans,solve(h[i]));
printf("%lld
",ans);
return 0;
}
}
signed main(){return yspm::main();}
Review
记得 (dp) 碰壁的时候想想贡献二分啥的