codeforeces 344 E Read Time

96 篇文章 0 订阅
64 篇文章 0 订阅

题意:

n个磁头去读取m个磁道,给出磁头和磁盘的初始位置(递增给出),问最少需要多少时间所有磁道均被读取。


思路:

二分答案还是很容易想到的,难点大概在于贪心。

在确定时间t后考虑:

由于有多个磁头,所有最左边的磁道肯定要由最左边的磁头去读取,但是如果没次都让磁头从左边开始读取,是不对的。最左边的磁道自然是要读取,但是贪心的思想下,我们应该让当前磁头在读取最左边的磁道的往右走的越远,因为这样就能在时间t以内读取更多的磁道。

当然还有一种情况是所有磁道都在当前最左边磁道的右边,那么直接往右走就好。

如果存在在左边的,那么当前磁头有两个选择,一种是先往右再往左,那么往右最多走(t-(h[i]-p[j]))/2的距离,第二种是先往左再往右,最多往右走t-2*(h[i]-p[j]),这个去最大值选择就行,依次这样跑h[i]。


另外需要注意的是时间t内如果无法到达最左边的磁头的话continue就行。


代码:

#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int maxn=1e5+5;
LL h[maxn];
LL H[maxn];
LL o[maxn];
bool book[maxn];

int main()
{
    int n, m;
    cin>>n>>m;
    int i, j;
    for(i=0; i<n; i++)
    {
        scanf("%lld", &h[i]);
    }
    for(i=0; i<m; i++)scanf("%lld", &o[i]);
    if(n==m)
    {
        for(i=0; i<m; i++)if(h[i]!=o[i])break;
        if(i==m)return 0*printf("0\n");
    }

    long long r=1e15+5, l=1;
    long long  mid;
    long long ans=0;
    int s=0;
    long long x;
    for(int e=0; e<150; e++)
    {
        mid=(l+r)>>1;
        s=0;
        for(i=0; i<n; i++)
        {
            x=mid;
            H[i]=h[i];
            if(abs(H[i]-o[s])>mid)continue;

            if(o[s]>=H[i])
            {
            for(j=s; j<m; j++)
            {
                if(o[j]-H[i]>mid)break;   
            }
                s=j;
            }
            else 
            {
                long long  e=H[i]-o[s];
                x=max(x-2*e, (x-e)/2);
                for(j=s; j<m; j++)
                {
                    if((o[j]-H[i])>x)break;
                }
                s=j;
            }
            if(s==m)break;
        }
        if(s==m)
        {
            r=mid-1;
            ans=mid;
        }
        else 
        {
            l=mid+1;
        }
    }
    cout<<ans<<endl;

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值