小红的数组操作(经典二分操作)
链接:https://ac.nowcoder.com/acm/contest/71993/D
来源:牛客网
小红拿到了一个数组,她每次可以进行如下操作:
选择一个数,使其减去 \(x\)。
小红希望\(k\)次操作之后,该数组的最大值尽可能小。请你求出这个尽可能小的最大值。
输入描述:
第一行输入三个正整数 \(n\)、\(k\) 和 \(x\),代表数组长度、操作次数以及每次操作减的数。
第二行输入 \(n\) 个正整数\(a_i\),代表小红拿到的数组。
\(1\leq n \leq 10^5\)
\(1\leq a_i,k,x \leq 10^9\)
输出描述:
一个整数,代表 \(k\) 次操作后,数组尽可能小的最大值。
示例1
输入
5 3 5
4 3 11 2 1
输出
3
说明
第一个数操作 1 次,第三个数操作 2 次,数组变成 [-1,3,1,2,1],最大值为 3。
经典二分,不多解释
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
ll n,k,x;
ll a[maxn];
bool check(ll ma){
ll z=0;
for(int i=1;i<=n;i++){
if(a[i]>ma){
z+=((a[i]-ma)/x);
if((a[i]-ma)%x>0){
z++;
}
}
if(z>k){
return false;
}
}
return k>=z;
}
int main(){
cin>>n>>k>>x;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ll l = -1e18,r = 1e9,ans;
while(r>=l){
ll mid=(l+r)/2;
if(check(mid)){
r=mid-1;
ans=mid;
}else{
l=mid+1;
}
}
cout<<ans<<endl;
return 0;
}