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;
}
为了更好的明天