[IAMOI R4] 木桶效应 题解
思路
观察答案为“最小值最大”,发现答案单调,考虑二分答案
考虑贪心。
将问题转化为,有若干个长度为
假设对于某个缝隙,我们用总长度为
发现长度为
首先按任意顺序,对于每个缝隙,用长度为
接着,如果还有多余的长度为
最后再用长度为
如果在 check 的时候直接排序,复杂度为
发现可以在二分前按照
但是没有卡双
code
双
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,k,h,c,p,lm,lk,l,r=1e18,mid,a[N],b[N];
bool check(int x){
c=0;
for(int i=1;i<=n;i++) if(a[i]<x) b[++c]=x-a[i];
if(!c) return true;
lm=m;
lk=k;
for(int i=1;i<=c;i++){
p=min(b[i]/h,lk);
b[i]-=p*h;
lk-=p;
}
sort(b+1,b+c+1,greater<int>());
for(int i=1;i<=c;i++){
if(lk&&b[i]>0){
b[i]-=h;
lk--;
}
}
for(int i=1;i<=c;i++){
if(lm-max(b[i],0ll)<0) return false;
lm-=max(b[i],0ll);
}
return true;
}
signed main(){
scanf("%lld%lld%lld%lld",&n,&m,&k,&h);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
while(l<=r){
mid=l+r>>1;
if(check(mid)) l=mid+1;
else r=mid-1;
}
printf("%lld",r);
return 0;
}