题意: 给出若干个木棍长度,你可以对每个木棍进行切割。

比如 有5个木棍,长度分别是4 4 4 5 3

你可以一次切长度为2的,那么4能切2刀,5能切2刀,3只能切一刀。总数加起来ans=2+2+2+2+1=9

题目问的就是一次切w刀,能使的ans>K.(K由题目给出),算出max(w)

数据范围:

n=2e5 木棍最大长度1e9

很显然这是一道二分的题目,二分一次切W刀,其实我们可以发现,最大切的次数应该是最大木棍长度,因为大于最大木棍长度没法切了嘛。

所以我们最大二分的区间是[1-1e9]

由于题目要最大值,我们只需要当ans>K的时候,记录最大值即可,注意二分的右边界需要+1,不然这组数据过不去
5 1
4 4 4 5 3

复杂度是n*logn

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <cctype>
#include <cmath>
#include <cassert>

#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

const int N=2e5+100;

ll a[N];
ll n,L;


int main()
{
    scanf("%lld%lld",&n,&L);
    ll maxx=-1e18;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        maxx=max(maxx,a[i]);
    }
//    if(L==1)
//    {
//        printf("%lld\n",maxx);
//        return 0;
//    }
    ll l=1;
    ll r=maxx+1;
    ll res=-1e18;
    while(l<r)
    {
        ll mid=(l+r)/2ll;
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=a[i]/mid;
        }
        //printf("mid:%lld ans:%lld\n",mid,ans);
        if(ans<L)
        {
            r=mid;
        }
        else
        {
            res=max(res,mid);
            l=mid+1;
        }
    }
    if(res==-1e18)
    {
        printf("0\n");
    }
    else
    {
        printf("%lld\n",res);
    }
    return 0;
}