Codeforces Round #307 (Div. 2) C. GukiZ hates Boxes (二分)

题目:

http://codeforces.com/problemset/problem/551/C

题意:

n堆货物,每堆货物有ai个箱子,共有m个人。

所有人从起点0出发,每个人每一秒中可以搬动一个箱子或者移动到下一个货堆。求出将所有的箱子清空最少需要的时间。

思路:

由于题目符合线性关系,所以应该想到二分。

移动所有的货物至少需要时间 n,最大需要时间 n+总箱子sum,分别设为左值和右值,则mid 值表示时间。

判断函数:判断在 mid时间中移动所有的箱子需要的总人数是否超过 提供的人数。

AC.

#include <iostream>
#include <cstdio>

using namespace std;
typedef long long ll;
const int MAX = 1e5+5;
int a[MAX];
int n, m, st;

bool check(ll x)
{
    int cnt = 0;
    ll sum = 0;
    for(int i = 1; i <= st; ++i) {
        sum += a[i];
        while(sum+i >= x) {
            sum -= (x-i); //多增加一个学生的话,除了走到i这个位置的时间,可以搬动的货物数(x-i)
            cnt++;
            if(cnt > m) return 0;
        }
    }
    if(cnt == m) {
        if(sum <= 0) return 1;
        else return 0;
    }
    return 1;
}

int main()
{
    //freopen("in", "r", stdin);
    while(~scanf("%d %d", &n, &m)) {
        ll sum = 0;
        ll l, r, ans;
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            if(a[i] != 0) st = i;
            sum += a[i];
        }
        l = st;
        r = l + sum; //时间

        while(l <= r) {
            ll mid = (l+r)/2;
            if(check(mid)) {
                ans = mid;
                r = mid-1;
            }
            else {
                l = mid+1;
            }
        }

        printf("%I64d\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值