Codeforces1355E Restorer Distance

比较厉害的一个题目吧

Description

link

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) 碰壁的时候想想贡献二分啥的

原文地址:https://www.cnblogs.com/yspm/p/12942767.html