牛牛的揠苗助长(二分&贪心)

牛牛的揠苗助长(二分&贪心)

题目传送门

假设水稻先不长,显然是数组 a a 中某一个数 a [ i ] a[i] 相等是最优的。依次类推

因此若不进行任何操作,数组 a a 变成数组 b b

有: b [ i ] = a [ i ] + d a y n + ( i < = d a y % n ) b[i]=a[i]+\dfrac{day}{n}+(i<=day\%n)

然后将数组 b b 排序,显然当 n n 为奇数时,肯定是选取 b [ n + 1 2 ] b[\dfrac{n+1}{2}]

n n 为偶数时也是选取 n + 1 2 = n 2 \dfrac{n+1}{2}=\dfrac{n}{2} ,而不是选取 n 2 + 1 \dfrac{n}{2}+1

这里做个证明:

因为花费的公式为:
c o s t = i × b [ i ] j = 1 i b [ i ] + j = i + 1 n b [ i ] ( n i ) × b [ i ] cost=i\times b[i]-\sum\limits_{j=1}^{i}b[i]+\sum\limits_{j=i+1}^{n}b[i]-(n-i)\times b[i]
对于前者:将 i = n 2 i=\dfrac{n}{2} 代入:


c o s t p r e = j = n 2 + 1 n b [ i ] j = 1 n 2 b [ i ] cost_{pre}=\sum\limits_{j=\frac{n}{2}+1}^{n}b[i]-\sum\limits_{j=1}^{\frac{n}{2}}b[i]
对于后者:将 i = n 2 + 1 i=\dfrac{n}{2}+1 代入:
c o s t p r e = j = n 2 + 1 n b [ i ] j = 1 n 2 b [ i ] + b [ n 2 + 1 ] cost_{pre}=\sum\limits_{j=\frac{n}{2}+1}^{n}b[i]-\sum\limits_{j=1}^{\frac{n}{2}}b[i]+b[\frac{n}{2}+1]

显然前者花费小。所以无论 n n 为奇数还是偶数, i = n + 1 2 i=\dfrac{n+1}{2} 都是最优解。

因为当 d a y = a n s day=ans 时能使所有数相等,那么 d a y = a n s + 1 , a n s + 2 day=ans+1,ans+2\dots 都可以通过使那个要增加的数减1来保持相等。所以接下来用对答案不断二分就可以了。

时间复杂度: O ( n l o g n × l o g n ) O(nlogn\times logn)
AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll a[N],n,ans,b[N];
bool jg(ll x){
	for(int i=1;i<=n;i++)
		b[i]=a[i]+x/n+(i<=x%n);
	sort(b+1,b+n+1);
	ll res=0;
	for(int i=1;i<=n;i++) res+=abs(b[i]-b[(n+1)>>1]);
	return  res<=x; 
}
int main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	ll l=1,r=1e14;
	while(l<=r){
		ll mid=(l+r)>>1;
		if(jg(mid)) r=mid-1,ans=mid;
		else l=mid+1; 
	}
	printf("%lld\n",ans);
	return 0;
}
原创文章 201 获赞 165 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/106019651