CodeForces - 343C Read Time (二分+贪心)

题意:有N个指针头,M个标记,用这N个针头扫描所有的标记,针头之间互不影响,求扫描完M个标记的最短时间
分析:二分搜答案,mid为时间限制,则只要所有的点在mid秒内被扫描到即可.
对于每个指针,若其左方没有待扫描标记,则它只需一路向右即可.若有需要扫描的标记,则有两种方式可以扫描,第一是先向左扫描到该标记,再向右一直走到;或先向右走一定距離,再向左返回掃描.
初始的上界R可任取一個指針掃描所有標記的耗時.

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
LL h[maxn],p[maxn];
bool vis[maxn];
int N,M;
bool check(LL limit)
{
    int pt = 1,j;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=N;++i){
        LL dist;
        if(p[pt]>h[i]){
            dist = h[i]+limit;
        }
        else{
            if(limit< h[i]-p[pt]) break;
            dist = max(limit+2*p[pt]-h[i],h[i]+(limit-h[i]+p[pt])/2);
        }
        for(j=pt;p[j]<=dist && j<=M ;++j){
            vis[j] =true;
        }
        if(vis[M]) return true;
        pt = j;
    }
    if(vis[M]) return true;
    else return false;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    while(scanf("%d %d",&N,&M)==2){
        for(int i=1;i<=N;++i){
            scanf("%I64d",&h[i]);
        }
        for(int i=1;i<=M;++i){
            scanf("%I64d",&p[i]);
        }
        LL L=0,R,mid;
        if(h[1]<p[1]){
            R = p[M]-h[1];
        }
        else{
            R = h[1] - p[1];
            if(h[1]<p[M]){
                R = min(R*2+p[M]-h[1],R+2*(p[M]-h[1]));
            }
        }
        LL ans=0;
        while(L<=R){
            mid = (L+R)>>1;
            if(check(mid)){
                R = mid-1;
                ans = mid;
            }
            else{
                L = mid+1;
            }
        }
        cout<<ans<<endl;
        //printf("%I64d\n",ans);
    }
    return 0;
}

posted @ 2018-09-07 12:30  xiuwenL  阅读(248)  评论(0编辑  收藏  举报