CodeForces

来源:互联网 发布:淘宝有哪些零食店铺 编辑:程序博客网 时间:2024/06/05 19:04

题意:有n个箱子形成的堆,现在有m个学生,每个学生每一秒可以有两种操作:
1: 向右移动一格
2: 移除当前位置的一个箱子
求移除所有箱子需要的最短时间。注意:所有学生可以同时行动。


思路:二分时间,判断当前限制的时间是否可以移除完所有箱子。那么如何判断呢? 设lim表示当前的时间限制,走到第i个堆花费i秒,从第n个堆开始处理,第i个堆需要的学生数是x=box[i]/(limi),可能x(limi)box[i],那么就剩余x(limi)box[i]的箱子可以拿,既然是从1走到i那么,一定可以移除前面的箱子,这样一直就行。复杂度O(n)

AC代码

#include <cstdio>#include <cmath>#include <cctype>#include <bitset>#include <algorithm>#include <cstring>#include <utility>#include <string>#include <iostream>#include <map>#include <set>#include <vector>#include <queue>#include <stack>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000") #define eps 1e-10#define inf 0x3f3f3f3f#define PI pair<int, int> typedef long long LL;const double pii = acos(-1.0);const int maxn = 1e5 + 5;int n, m;LL box[maxn], pbox[maxn];bool check(LL lim) {    LL rest = 0, cnt = m;    for(int i = n-1; i >= 0; --i) {        pbox[i] = box[i];        if(rest >= pbox[i]) {            rest -= pbox[i];            pbox[i] = 0;        }        else {            pbox[i] -= rest;            rest = 0;        }        LL dis = i+1;        if(pbox[i] == 0) continue;        if(lim <= dis) return false;        //pbox[i] <= x*(lim-dis)        LL num = (LL)ceil(1.0*pbox[i]/(lim-dis));        if(num > cnt) return false;        cnt -= num;        rest += num*(lim-dis) - pbox[i];    }    return true;}LL solve(LL x, LL y) {    while(x < y) {        LL mid = (x+y) / 2;        if(check(mid)) y = mid;        else x = mid+1;    }    return y;}int main() {    while(scanf("%d%d", &n, &m) == 2) {        LL sum = 0;        for(int i = 0; i < n; ++i) {            scanf("%lld", &box[i]);            sum += box[i] + i;        }        printf("%lld\n", solve(0, sum+5));    }    return 0;}

如有不当之处欢迎指出!

原创粉丝点击