cf343c 二分答案+模拟

/*
怎么判断能否在时间k内完成扫描
贪心:每次取出最靠左边的磁头去扫描最左边的,然后再往右扫描即可 
如果当前点无法扫到最左侧点,那么后继点一样无法扫到 
*/
#include<bits/stdc++.h>
#define maxn 100005
#define ll long long 
using namespace std;

int n,m;
ll h[maxn],p[maxn];
 
int judge(ll x){
    ll time1,time2;
    int index=1;
    for(int i=1;i<=n;i++){
        if(h[i]-p[index]>x) return 0;
        if(p[index]>=h[i]){//直接往右扫描 
            while(index<=m && p[index]<=x+h[i])
                index++;
            if(index>m) return 1;// 
        }
        else {
            time1=(x-(h[i]-p[index]))/2;
            time2=x-(h[i]-p[index])*2;
            time1=max(time1,time2); //先往左在往右或者先往右再往左的最长右走时间 
            while(index<=m && p[index]<=time1+h[i])
                index++;    
            if(index>m) return 1;
        }
    }
    return 0;
}

int main(){
    while(scanf("%d%d",&n,&m)==2){
        for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
        for(int i=1;i<=m;i++) scanf("%lld",&p[i]);
        ll l=0,r=max(h[n],p[m])*2,ans=0;
        while(l<=r){
            ll mid=l+r>>1;
            if(judge(mid))
                ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%I64d
",ans);
    } 
} 
原文地址:https://www.cnblogs.com/zsben991126/p/10141326.html