codeforces 551c[补]

BNUZ比赛训练【补】

一道正常的cf的c题,比赛过程中想到用二分,但是贪心的思路没想好,一直没下手敲,赛后看了下题解,果然自己连贪心都不会了,简直菜啊。


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

题目大概意思:
有n个位置,每个位置上有一种东西,需要消除他们,有m个学生,这些学生从位置0开始出发,一直只能向右走,每走一步需要花费一秒钟,每消除每个位置上的一样东西需要花费一秒钟,学生可以同时出发,问最短将这些东西消除的时间为多长。


其实很容易想到,二分答案,直接二分所需要的时间,那重点是就是怎么check了,比赛的时候由于菜,还有20分钟的时候才看过这道题,然后一开始没思路,想到二分的时候已经只有10分钟了。。然而还是那种没想到贪心的情况,所以没敲。。赛后再看回来。这个贪心真的是灰常涨姿势。
先二分所需要的时间,然后每一个学生每次优先走到最后一个所需要工作的箱子,如果可以删除完就删除完,删除完后往前移一位(这里我们把他这个人当做是先到了那个位置,工作完了,再走到后面,这样的话,步行时间永远只是走到最后面的时间),然后一直模拟即可。

这里要注意一个大坑,就是他后面可能有很多个0,这样的话,就不需要去访问那些位置了,因为永远走不到,所以需要开始的时候把那些没用的去掉。在这wa了3发才反应过来。。。

下面贴上棒棒的代码

/*
@resouces: codeforces 551C
@date: 2017-3-3
@author: QuanQqqqq
@algorithm: binary search + greedy 
*/
#include <bits/stdc++.h>

#define ll long long
#define maxn 100050

using namespace std;

ll a[maxn],b[maxn];
ll n,m;

bool check(ll t){
    ll last = n,p = m,temp;
    for(ll i = 1;i <= n;i++){
        b[i] = a[i];
    }
    while(p-- && last){
        ll hast = t - last;
        for(int i = last;i >= 1;i--){
            if(hast > b[i]){
                hast -= b[i];
                b[i] = 0;
                last--;
            } else {
                b[i] -= hast;
                break;
            }
        }
    }
    temp = n;
    while(temp){
        if(b[temp]){
            break;
        }
        temp--;
    }
    return temp == 0;
}

ll binary_search(ll l,ll r){
    ll mid;
    while(l <= r){
        mid = l + r >> 1;
        if(check(mid)){
            r = mid - 1;
        } else {
            l = mid + 1;
        }
    }
    if(!check(mid))
        mid++;
    return mid;
}

int main(){
    scanf("%lld %lld",&n,&m);
    ll maxt = n;
    ll judge = 0;
    for(ll i = 1;i <= n;i++){
        scanf("%lld",&a[i]);
        judge += a[i];
    }
    if(!judge){
        printf("0\n");
        return 0;
    }
    while(a[n] == 0)
        n--;
    printf("%lld\n",binary_search(n,1e15));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值