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

来源:互联网 发布:虚拟软件下载 编辑:程序博客网 时间:2024/05/21 18:49

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 111111ll 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);    }}
0 0
原创粉丝点击