CF1873E Building an Aquarium 题解

这题看到第一眼就是二分。

思路

单调性

二分最关键的东西是单调性在哪。单调性是如果高度越高,需要的水就越多,高度越矮,要用的水越少。所以单调性就得出了。


如何求需要的水呢?

\[\sum_{i=1}^{i \le n} \max(0,mid-a_{i}) \]

\(mid\) 表示现在墙的高度。墙高度减去水池底部的高度,就是这一列需要的水。如果水池底部的高度,比墙还高,那就会是负数,但实际上是不要水的,所以和零取 \(\max\)

求出需要的水就好办了,如果小于等于 \(x\),就去右半部分查找,同时更新答案,否则去左半部分继续查找。

注意,\(r\) 不要设太大,要不然搞出来的 \(mid\) 再算需要的水时会爆炸,导致变成负数,结果就比 \(x\) 小,会被判断成为合法的答案了。 \(2\times 10^{9}\) 基本够了,因为最小的 \(n\) 是一,最大的 \(x\)\(\max_{i=1}^{i \le n} a_{i}\)\(10^{9}\)\(x \div n+\max_{i=1}^{i \le n} a_{i}=2 \times 10^{9}\)

AC CODE

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,x,a[200005],maxx,ans;
int check(int mid){
	int sum=0;
	for(int i=1;i<=n;i++){
		sum+=max(0ll,mid-a[i]);
	}
	return sum;
}
signed main(){
	int T;
	cin>>T;
	while(T--){
		maxx=ans=0;
		scanf("%lld%lld",&n,&x);
		for(int i=1;i<=n;i++){
			scanf("%lld",a+i);
		}
		int l=0,r=2e9+5;
		while(l<=r){
			int mid=l+r>>1;
//			cout<<l<<" "<<r<<endl;
			if(check(mid)<=x){
				l=mid+1;
				ans=max(mid,ans);
			}
			else{
				r=mid-1;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2023-10-16 14:16  Xu_dh  阅读(60)  评论(0)    收藏  举报