• CF GukiZ hates Boxes 【二分+贪心】


    Professor GukiZ is concerned about making his way to school, because massive piles of boxes are blocking his way.

    In total there are n piles of boxes, arranged in a line, from left to right, i-th pile (1 ≤ i ≤ n) containing ai boxes. Luckily, m students are willing to help GukiZ by removing all the boxes from his way. Students are working simultaneously. At time 0, all students are located left of the first pile. It takes one second for every student to move from this position to the first pile, and after that, every student must start performing sequence of two possible operations, each taking one second to complete. Possible operations are:

    If i ≠ n, move from pile i to pile i + 1;
    If pile located at the position of student is not empty, remove one box from it.
    GukiZ's students aren't smart at all, so they need you to tell them how to remove boxes before professor comes (he is very impatient man, and doesn't want to wait). They ask you to calculate minumum time t in seconds for which they can remove all the boxes from GukiZ's way. Note that students can be positioned in any manner after t seconds, but all the boxes must be removed.

    Input
    The first line contains two integers n and m (1 ≤ n, m ≤ 105), the number of piles of boxes and the number of GukiZ's students.

    The second line contains n integers a1, a2, ... an (0 ≤ ai ≤ 109) where ai represents the number of boxes on i-th pile. It's guaranteed that at least one pile of is non-empty.

    Output
    In a single line, print one number, minimum time needed to remove all the boxes in seconds.

    Examples
    Input
    2 1
    1 1
    Output
    4
    Input
    3 2
    1 0 2
    Output
    5
    Input
    4 100
    3 4 5 4
    Output
    5
    Note
    First sample: Student will first move to the first pile (1 second), then remove box from first pile (1 second), then move to the second pile (1 second) and finally remove the box from second pile (1 second).

    Second sample: One of optimal solutions is to send one student to remove a box from the first pile and a box from the third pile, and send another student to remove a box from the third pile. Overall, 5 seconds.

    Third sample: With a lot of available students, send three of them to remove boxes from the first pile, four of them to remove boxes from the second pile, five of them to remove boxes from the third pile, and four of them to remove boxes from the fourth pile. Process will be over in 5 seconds, when removing the boxes from the last pile is finished.
    【题意】:有n个空地(1~n),空地上有a[i]块石头,m个学生,每个学生在0这个位置,有两个操作均需要消耗1秒
    操作1:将当前所在位置的石头删除
    操作2:往右走一个位置,问删除所有空地上的石头需要花费的最少时间
    【分析】:二分枚举答案,贪心判断是否满足 即可。关键在于如何贪心,我们可以 从1向最后一个有石头的位置枚举(因为后面的都无关了,而且这样做方便后面的贪心),将中间遇到的石头都加起来,如果此时到当前位置所需花费时间+删除石头所需时间>=枚举值,这时候就需要一个学生,从0~枚举时间 对这段区间进行删除石头的操作,此时可以完美利用该学生,使其在枚举的时间内一刻不停地干活,剩下以此类推
    二分总时间,贪心选择。已知总共有m个人,那么每个人的总时间都已经知道了,
    我们从后往前或者从前往后贪心都可以,先用尽一个人的时间,不够再补,只要出现所有人的时间都用完了还不够的情况下返回false。
    【详细注释代码】

    #include<bits/stdc++.h>
    const double eps = 1e-8;
    #define ll long long
    using namespace std;
    
    ll a[100050];
    int n,m;
    ll ans,sum;
    ll st,ed;
    int Check(ll x)//二分时间
    {
        int cnt = m; //学生数量
        ll sum = 0;
        for(int i = 1; i<=st; i++)
        {
            sum+=a[i]; //总箱子个数 第i个位置
            //如果此时到当前位置所需花费时间i+删除石头所需时间sum>=枚举值x,这时候就需要一个学生
            while(sum + i >= x)  //当箱子总数sum加上位置i大于时间x时
            {
                //对于已走的路程i,那么一个人有x-i(x是总时间,i是走路时间;故x-i是搬砖干活时间)时间来搬箱子,所以每增加一人,时间消耗可以减少x-i
                sum -= x-i;  //移动到了x-i位置以后,每增加一个学生就可以搬走一个箱子
                cnt--;  //消耗一个学生
                if(cnt<0) return 0;
            }
        }
        if(cnt==0)//删除所有空地上的石头需要花费的最少时间
        {
            if (sum <= 0) return 1;
            else return 0;
        }
        return 1;
    }
    
    int main()
    {
    
        while(cin>>n>>m)
        {
            sum = 0;
            for(int i =1; i<=n;i++)
            {
                scanf("%I64d",&a[i]);
                if(a[i])
                    st = i;
                sum += a[i];
            }
            ed = st + sum;
            ll L = st,R = ed;
            while(L<=R)
            {
                ll mid =(L+R)/2;
                if(Check(mid))
                {
                    ans = mid;
                    R = mid - 1;
                }
                else
                {
                    L = mid + 1;
                }
            }
            cout<<ans<<endl;
        }
    }
    
    /*
    T 这个格子是一个建筑物
    
    G 这是一块空地
    
    M 这是Wells和小姐姐浪漫的地方,当然也是个空地
    
    D 这是Wells的家
    
    H 这是一个狗仔队的窝点
    
    7 3
    TTTTTTT
    TGGGGGT
    TGGGGGT
    MGGGGGD
    TGGGGGT
    TGGGGGT
    TGHHGGT
    */
    
    
  • 相关阅读:
    CSS盒子模型
    getContextPath、getServletPath、getRequestURI、request.getRealPath的区别
    MYSQL中的CASE WHEN END AS
    单点登录的精华总结
    git&github
    June 21st 2017 Week 25th Wednesday
    June 20th 2017 Week 25th Tuesday
    June 19th 2017 Week 25th Monday
    June 18th 2017 Week 25th Sunday
    June 17th 2017 Week 24th Saturday
  • 原文地址:https://www.cnblogs.com/Roni-i/p/9359544.html
Copyright © 2020-2023  润新知