前言
题意 :
给你一个 n n n和 k k k,以及一个长度为 n n n的 a [ ] a[] a[]
两种操作 :
- 选择一个下标使得 a [ i ] = a [ i − 1 ] a[i] = a[i-1] a[i]=a[i−1]
- 选择两个下标使得 a [ i ] = a [ j ] a[i]=a[j] a[i]=a[j]
询问最小次数使得 ∑ i = 1 n a [ i ] < = k \sum_{i=1}^na[i] <=k ∑i=1na[i]<=k
思路
根据贪心的思想,我们肯定是 将最小的那个减到一定小的时候 ,然后再复制给其他
的数。
在不考虑选哪一个操作的情况下 , 显然都是可以优化 s u m sum sum的
因此答案是满足单调的
因此我们可以使用二分进行枚举操作次数
区间 l = 1 , r = n − 1 + m i n ( a [ ] ) l=1,r=n-1+min(a[]) l=1,r=n−1+min(a[]),最后在暴力 c h e c k check check即可
Mycode
const int N = 2e5+10;
int a[N];
ll sum,k;
int n;
bool check(int c){
ll sum = 0;
for(int i = 0; i<=min(n-1,c);i++){
sum+=a[i];
if(sum - 1ll*(a[n] -c+i)*i + c - i >= k)
return 1;
}
return 0;
}
void solve()
{
cin>>n>>k;
sum =0 ;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
k = sum - k ;
if(k<= 0){
cout<<0<<endl;
return;
}
sort(a+1,a+1+n,greater<int>());
int l = 1, r = n-1+a[n];
while(l <= r){
int mid = l+r>>1;
if(check(mid))
r = mid - 1;
else
l = mid + 1;
}
cout<<l<<endl;
}