题目传送门:CF875E
洛谷入口
题目大意:
(有两个人在一根数轴上送货,起初一个人在s1, 一个人在s2)
(一共有 n 个订单要送,严格按照时间顺序,第 i 个订单要送到数轴上的 x_i 位置。)
(每个订单恰好一个人去送,且在这个过程当中另一人始终保持在原地不动)
(你可以安排每个订单由哪个人去送,从而最小化整个过程中两个人之间的最大距离)
数据范围
(circ) (1le nle10^5)
(circ) (0le s1,s2le10^9)
(circ) (0le x_ile10^9)
(数据保证 s_1,s_2,x_1,x_2,...,x_n 两两不等)
题解
这题中提到“最小化最大距离”
我们会想到去二分这个距离
然后要尝试用O(n)的时间复杂度
判断这个二分出的距离是否可能
那么按题意,在最后会有一个人(称为A)在(a_n)的位置上
倒过来想,会产生一个区间,即:(Q_n=[a_n-x,a_n+x])
并假设初始所有区间(Q_i=[a_i-x,a_i+x])
若当时开始讨论i这个点
另一个人(称为B)在区间(Q_{i+1})内
那可以B直接走这个i点,区间(Q_i)不作修改
但如果B不在(Q_{i+1})内
那只能由A亲自走i点,区间就是(Q_i和Q_{i+1})的交集
然后要防止这个区间被刷为空集,即l<r
一旦不符合就表示不行
安排完区间(Q_1)后要保证在这个区间内
s1和s2中至少有一个在里面
如果这些阻挠都没有困住这个x,恭喜它,它是可能的答案
然后二分算法就不多赘述了
总体时间复杂度(O(nlog n))
(好像这题对于各位visitor来说应该很简单,但是还是细解了QwQ)
此题完结!!!下见代码↓↓↓
AC代码
#include<bits/stdc++.h>
using namespace std;
int a[100010],s1,s2,ans,n;
bool check(int x){
int l=a[n]-x,r=a[n]+x;
for(int i=n-1;i>=1;i--){
if(a[i]>=l&&a[i]<=r)l=a[i]-x,r=a[i]+x;
else l=max(a[i]-x,l),r=min(a[i]+x,r);
if(l>r)return false;
}
if((s1<l||s1>r)&&(s2<l||s2>r))return false;
return true;
}
int main(){
cin>>n>>s1>>s2;
for(int i=1;i<=n;i++)cin>>a[i];
int l=abs(s1-s2),r=1e9;
while(l<=r){
int mid=l+r>>1;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans;
}
(仅有24行……)