ural 1998 The old Padawan (模拟+二分)

题意:

有一个人捡按一定顺序捡石头,每秒都能捡起一个,但是他有时会分心,这是不但不能举石头,

而且手中的石头还会掉,直到没有石头可以掉下来或者掉下来的石头的总重量>k。依次给出n个

石头的重量和m个他分心的时间点,问他需要多长时间把石头全部举起。


分析:

n、m的范围都是 10^5,在不分心的时间都是每秒举起一个石头,那么用ti表示他分心的时间点,则

ti秒时,他的pos=p1,t(i+1)秒时在pos = p1+t(i+1)-ti-1处,然后要看他丢掉石头后回到哪个位置。

开始用O(n)的复杂度  去找那个位置j判断sum[pos+1]-sum[j]是否>k超时。

后来想到这个位置其实可以用二分 O(logn)的复杂度找出。


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#define maxn 100010

using namespace std;
typedef long long ll;

int t[maxn];
ll sum[maxn];

int check(int l,int r,ll val)
{
    int p;
    while(l<=r)
    {
        int mid = (l+r)>>1;
        if(sum[mid] < val)
        {
            p = mid;
            l = mid+1;
        }
        else r = mid-1;
    }
    return p;
}

int main()
{
    int n,m,k,w;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        memset(t,0,sizeof(t));
        sum[0] = 0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&w);
            sum[i] = sum[i-1]+w;
        }
        for(int i=1;i<=m;i++)
            scanf("%d",&t[i]);
        int pos = 0,ans = 0;
        for(int i=1;i<=m;i++)
        {
            if(pos+t[i]-t[i-1]-1>=n)
            {
                ans += (n-pos);
                pos = n;
                break;
            }
            pos+=(t[i]-t[i-1]-1);
            ans = t[i];
            pos = check(1,pos+1,sum[pos]-k);
        }
        if(pos<n)
            ans += (n-pos);
        printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值