二分,求直线上覆盖所有点的最短时间
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 }
以上是关于二分,求直线上覆盖所有点的最短时间的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ2525[Poi2011]Dynamite 二分+树形DP