二分,求直线上覆盖所有点的最短时间

Posted klaycf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分,求直线上覆盖所有点的最短时间相关的知识,希望对你有一定的参考价值。

 

http://codeforces.com/group/aUVPeyEnI2/contest/230300/problem/E

参考自:https://blog.csdn.net/u013508213/article/details/49594691

题意:

给n个内存读取指针头,m个需要访问的内存地址(1??n,?m??1051?≤?n,?m?≤?105) ,每一秒钟,指针头可以向左移动或者向右移动一个单位,问最少需要多少时间,能把这些内存地址访问完。 

solution:

二分固定时间t,ok函数的写法是:
当当前的指针头小于当前需要访问的内存节点时,指针头不断往前移动就好了;
当当前的指针头大于当前需要访问的内存节点时,需要做个比较:
首先是当前指针头先往左移动到需要访问的内存节点,再移动回来往前移动,此时还可以往前移动的时间是t?2?(head[i]?track[cnt])t?2?(head[i]?track[cnt]);
然后是当前指针头先往右移动足够远,然后再回来访问需要访问的内存节点,此时可以往前移动的时间是(t?(head[i]?track[cnt]))/2(t?(head[i]?track[cnt]))/2。
取二者大的往前移动即可。
若计数cnt>=m,说明时间充裕。

技术分享图片
 1 /*************************************************************************
 2     > File Name:  
 3     > Author: QWX
 4     > Mail: 
 5     > Created Time: 2018/10/11 18:11:28
 6  ************************************************************************/
 7 
 8 
 9 //{{{ #include
10 #include<iostream>
11 #include<cstdio>
12 #include<algorithm>
13 #include<vector>
14 #include<cmath>
15 #include<queue>
16 #include<map>
17 #include<set>
18 #include<string>
19 #include<cstring>
20 #include<complex>
21 #include<bits/stdc++.h>
22 #define mp make_pair
23 #define pb push_back
24 #define first fi
25 #define second se
26 #define pw(x) (1ll << (x))
27 #define sz(x) ((int)(x).size())
28 #define all(x) (x).begin(),(x).end()
29 #define rep(i,l,r) for(int i=(l);i<(r);i++)
30 #define per(i,r,l) for(int i=(r);i>=(l);i--)
31 #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
32 #define cl(a,b) memset(a,b,sizeof(a))
33 #define fastio ios::sync_with_stdio(false);cin.tie(0);
34 #define lson l , mid , ls
35 #define rson mid + 1 , r , rs
36 #define INF 0x3f3f3f3f
37 #define LINF 0x3f3f3f3f3f3f3f3f
38 #define ll long long
39 #define ull unsigned long long
40 #define dd(x) cout << #x << " = " << (x) << "," 
41 #define de(x) cout << #x << " = " << (x) << "
" 
42 #define endl "
"
43 using namespace std;
44 //}}}
45 
46 const int N=1e5+7;
47 ll a[N],b[N];
48 int n,m;
49 bool check(ll t)
50 {
51     int cnt=0;
52     rep(i,0,n){
53         if(t<abs(a[i]-b[cnt]))continue;
54         ll d=a[i];
55         if(a[i]<b[cnt])d+=t;
56         else d+=max((t-(a[i]-b[cnt]))/2,t-2*(a[i]-b[cnt]));
57         while(cnt<m&&b[cnt]<=d)cnt++;
58     }
59     return cnt>=m;
60 }
61 
62 int main()
63 {
64     fastio;
65     cin>>n>>m;
66     rep(i,0,n)cin>>a[i];
67     rep(i,0,m)cin>>b[i];
68     ll l=0,r=1e11,ans=0;
69     while(l<=r){
70         ll mid=(l+r)>>1;
71         if(check(mid))r=mid-1,ans=mid;
72         else l=mid+1;
73     }
74     cout<<ans<<endl;
75     return 0;
76 }
View Code

 







以上是关于二分,求直线上覆盖所有点的最短时间的主要内容,如果未能解决你的问题,请参考以下文章

读——二分

二分图定理及证明

BZOJ2525[Poi2011]Dynamite 二分+树形DP

什么是两点之间的距离 什么定义

LeetCode 1723 完成所有工作的最短时间[二分法 回溯] HERODING的LeetCode之路

Abandoned country HDU - 5723