Codeforces Round #540 (Div. 3) D. Coffee and Coursework(二分)

时间:2022-06-19
本文章向大家介绍Codeforces Round #540 (Div. 3) D. Coffee and Coursework(二分),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

版权声明:欢迎转载,若转载,请标明出处,如有错误,请指点,也欢迎大佬们给出优化方法 https://blog.csdn.net/Charles_Zaqdt/article/details/87774418

题目链接:https://codeforces.com/contest/1118/problem/D2

       题意是有n杯咖啡,m页论文,然后是每杯咖啡所含的咖啡因,然后每天可以喝任意杯咖啡,如果这一天喝了很多杯咖啡的话,第一杯咖啡的咖啡因就是ai,第二杯的咖啡因就是ai-1,第三杯就是ai-2,一个咖啡因可以完成1页的论文,问最少需要几天可以写完这篇论文。

       对于D1和D2的不同点就在于数据范围不同,那么D2可以过的话,D1就一定能过,对于D1来说,n只有100,所以写论文的天数最多也就100天,所以我们可以从1到n暴力枚举天数,如果可行i就是最少天数,那么判断是否可行的方法就是我们先让i天每天喝一杯咖啡,而且是咖啡因含量从大到小排序,如果不够m页的话,再依次让i天每天喝两杯咖啡,以此类推看能否完成m页的论文。那么D2就不能1-n枚举了,但是也不难想到二分天数,然后也是根据这个条件去判断就好了。下面只贴D2的呆码。


AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m;
ll pre[200005];

bool cmp(ll a,ll b){
  return a > b;
}

bool Check(ll x){
  ll ans = 0;
  for(int i=0;i<n;i++){
    ans += max(0LL, (ll)pre[i] - (i / x));
  }
  return ans >= m;
}

int main()
{
  scanf("%lld%lld",&n,&m);
  ll sum = 0;
  for(int i=0;i<n;i++){
    scanf("%lld",&pre[i]);
    sum += pre[i];
  }
  sort(pre, pre + n, cmp);
  if(sum < m){
    puts("-1");
    return 0;
  }
  ll l = 1, r = n, mid, ans = -1;
  while(l <= r){
    mid = (l + r) >> 1;
    if(Check(mid)){
      r = mid - 1;
      ans = mid;
    }
    else{
      l = mid + 1;
    }
  }
  cout<<ans<<endl;
  return 0;
}