GYM 100285 I. The old Padawan(二分+简单模拟)

Description
有一个人捡按一定顺序捡石头,每秒都能捡起一个,但是他有时会分心,这是不但不能举石头,而且手中的石头还会掉,直到没有石头可以掉下来或者掉下来的石头的总重量>k。依次给出n个石头的重量和m个他分心的时间点,问他需要多长时间把石头全部举起
Input
第一行三个整数n,m,k分别表示石头数量,分心次数以及每次分心掉落石头质量的下限,之后n行每行一个整数分别表示每个石头的质量,最后m行每行一个整数表示分心的时刻
Output
输出需要多长时间把石头全部举起
Sample Input
5 1 4
1
2
3
4
5
4
Sample Output
8
Solution
n、m的范围都是 10^5,在不分心的时间都是每秒举起一个石头,那么用ti表示他分心的时间点,则ti秒时,他的pos=p1,t(i+1)秒时在pos = p1+t(i+1)-ti-1处,然后二分求出他丢掉石头后回到哪个位置,即sum[pos+1]-sum[j]>k的pos点即可
Code

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
#define maxn 111111
ll n,m,k,sum[maxn],t[maxn];
ll goto_bound(ll l,ll r,ll v)
{
    ll ans;
    while(l<=r)
    {
        ll mid=(l+r)/2;
        if(sum[mid]<v)
        {
            ans=mid;
            l=mid+1;
        }
        else
            r=mid-1;
    }
    return ans;
}
int main()
{
    while(~scanf("%I64d%I64d%I64d",&n,&m,&k))
    {
        memset(sum,0,sizeof(sum));
        for(ll i=1;i<=n;i++)
        {
            ll temp;
            scanf("%I64d",&temp);
            sum[i]=sum[i-1]+temp;
        }
        t[0]=0;
        for(ll i=1;i<=m;i++)
            scanf("%I64d",&t[i]);
        ll ans=0,pos=0;
        for(ll i=1;i<=m;i++)
        {
            if(pos+t[i]-t[i-1]-1>=n)//如果在下一次分心点之前已经将全部石头举起 
            {
                ans+=n-pos;
                pos=n;
                break;
            }
            ans=t[i];
            pos+=t[i]-t[i-1]-1;
            pos=goto_bound(1,pos+1,sum[pos]-k);//二分找到掉落石头后的位置 
        }
        if(pos<n)
            ans+=n-pos;
        printf("%I64d\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值