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;
}