二分-牛客寒假集训营5-D-牛牛与牛妹的约会
题目:
题意:
输 入 直 角 坐 标 系 中 N 个 点 的 坐 标 x i , y i , 求 N 个 点 v 1 , v 2 , . . . , v N 中 任 一 点 到 达 X 轴 上 某 定 点 距 离 的 最 大 值 , 输 出 这 些 最 大 值 当 中 的 最 小 值 。 输入直角坐标系中N个点的坐标x_i,y_i,求N个点v_1,v_2,...,v_N中任一点到达X轴上某定点距离的最大值,\\输出这些最大值当中的最小值。 输入直角坐标系中N个点的坐标xi,yi,求N个点v1,v2,...,vN中任一点到达X轴上某定点距离的最大值,输出这些最大值当中的最小值。
样 例 中 , 三 个 点 到 点 ( x , 0 ) 的 距 离 分 别 是 ∣ x ∣ 、 ∣ 2 − x ∣ 、 ( x − 0 ) 2 + ( 0 − 2 ) 2 = x 2 + 4 \\样例中,三个点到点(x,0)的距离分别是|x|、|2-x|、\sqrt{(x-0)^2+(0-2)^2}=\sqrt{x^2+4} 样例中,三个点到点(x,0)的距离分别是∣x∣、∣2−x∣、(x−0)2+(0−2)2=x2+4
容 易 发 现 , 当 x > = 0 时 , x 2 + 4 > = x 2 + 4 − 4 x = ( 2 − x ) 2 = ∣ 2 − x ∣ , 且 x 2 + 4 > x 2 = ∣ x ∣ , 容易发现,当x>=0时,\sqrt{x^2+4}>=\sqrt{x^2+4-4x}=\sqrt{(2-x)^2}=|2-x|,且\sqrt{x^2+4}>\sqrt{x^2}=|x|, 容易发现,当x>=0时,x2+4>=x2+4−4x=(2−x)2=∣2−x∣,且x2+4>x2=∣x∣,
因 此 , 当 x > = 0 时 , 3 个 点 到 X 轴 上 的 点 ( x , 0 ) 的 最 大 距 离 是 点 ( 0 , 2 ) 到 ( x , 0 ) 的 距 离 x 2 + 4 > = 2 。 因此,当x>=0时,3个点到X轴上的点(x,0)的最大距离是点(0,2)到(x,0)的距离\sqrt{x^2+4}>=2。 因此,当x>=0时,3个点到X轴上的点(x,0)的最大距离是点(0,2)到(x,0)的距离x2+4>=2。
对 x < 0 时 , ∣ x ∣ < x 2 + 4 < x 2 + 4 − 4 x = ∣ 2 − x ∣ , 最 大 值 是 点 ( 2 , 0 ) 到 点 ( x , 0 ) 的 距 离 ∣ 2 − x ∣ > 2 。 对x<0时,|x|<\sqrt{x^2+4}<\sqrt{x^2+4-4x}=|2-x|,最大值是点(2,0)到点(x,0)的距离|2-x|>2。 对x<0时,∣x∣<x2+4<x2+4−4x=∣2−x∣,最大值是点(2,0)到点(x,0)的距离∣2−x∣>2。
所 以 距 离 最 大 值 的 最 小 值 是 2 , 在 点 ( 0 , 0 ) 处 取 得 。 所以距离最大值的最小值是2,在点(0,0)处取得。 所以距离最大值的最小值是2,在点(0,0)处取得。
题解:
目 标 就 是 找 到 所 有 点 到 X 轴 某 一 点 最 大 值 的 最 小 值 。 目标就是找到所有点到X轴某一点最大值的最小值。 目标就是找到所有点到X轴某一点最大值的最小值。
结 合 数 据 范 围 应 该 是 个 O ( N l o g 2 N ) 的 做 法 , 又 因 为 点 在 X 轴 上 , 且 要 求 最 小 值 , 考 虑 二 分 法 。 结合数据范围应该是个O(Nlog_2N)的做法,又因为点在X轴上,且要求最小值,考虑二分法。 结合数据范围应该是个O(Nlog2N)的做法,又因为点在X轴上,且要求最小值,考虑二分法。
接 着 是 判 断 条 件 的 选 取 , 若 考 虑 二 分 最 终 答 案 — — 最 小 值 , 那 么 由 于 点 的 未 知 , 无 法 计 算 各 点 到 X 轴 上 点 的 距 离 。 接着是判断条件的选取,若考虑二分最终答案——最小值,那么由于点的未知,无法计算各点到X轴上点的距离。 接着是判断条件的选取,若考虑二分最终答案——最小值,那么由于点的未知,无法计算各点到X轴上点的距离。
因 此 考 虑 二 分 取 到 最 小 值 时 X 轴 上 的 点 。 因此考虑二分取到最小值时X轴上的点。 因此考虑二分取到最小值时X轴上的点。
二
分
X
轴
上
的
点
m
i
d
,
每
次
枚
举
计
算
N
个
点
到
该
点
距
离
的
最
大
值
,
同
时
p
o
s
记
录
最
大
值
点
的
下
标
i
,
二分X轴上的点mid,每次枚举计算N个点到该点距离的最大值,同时pos记录最大值点的下标i,
二分X轴上的点mid,每次枚举计算N个点到该点距离的最大值,同时pos记录最大值点的下标i,
r
e
s
记
录
这
些
最
大
值
中
的
最
小
值
,
因
为
要
求
最
大
值
中
的
最
小
值
,
所
以
m
i
d
应
当
靠
近
p
o
s
,
使
得
最
大
值
变
小
。
res记录这些最大值中的最小值,因为要求最大值中的最小值,所以mid应当靠近pos,使得最大值变小。
res记录这些最大值中的最小值,因为要求最大值中的最小值,所以mid应当靠近pos,使得最大值变小。
若
m
i
d
>
=
x
[
p
o
s
]
,
说
明
二
分
的
点
m
i
d
在
p
o
s
的
右
边
,
更
新
r
=
m
i
d
,
反
之
更
新
l
=
m
i
d
,
最
后
输
出
答
案
r
e
s
。
若mid>=x[pos],说明二分的点mid在pos的右边,更新r=mid,反之更新l=mid,最后输出答案res。
若mid>=x[pos],说明二分的点mid在pos的右边,更新r=mid,反之更新l=mid,最后输出答案res。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x7fffffff
using namespace std;
const int maxn=1e5+5;
int N;
double x[maxn],y[maxn];
double mdis,res=inf,mlx=-1,mrx=1;//这里左端点mlx应当要小于mrx,避免出现二者相等的情况
double dis(int a,double b)
{
return sqrt((x[a]-b)*(x[a]-b)+y[a]*y[a]);
}
int main()
{
cin>>N;
for(int i=0;i<N;i++)
{
scanf("%lf%lf",&x[i],&y[i]);
mlx=min(mlx,x[i]),mrx=max(mrx,x[i]);
}
double l=mlx,r=mrx;
while(r-l>1e-6)
{
double mid=(l+r)/2;
int pos;
mdis=0;//要计算每一次的最大值
for(int i=0;i<N;i++)
if(mdis<=dis(i,mid))
{
pos=i;
mdis=dis(i,mid);
}
res=min(res,mdis);
if(mid>=x[pos]) r=mid;
else l=mid;
}
printf("%.4f\n",res);
return 0;
}
总结:
- 实 数 二 分 计 算 m i d 时 不 可 用 l + r > > 1 。 实数二分计算mid时不可用 \ l+r>>1。 实数二分计算mid时不可用 l+r>>1。
- 实 数 二 分 循 环 条 件 不 能 判 l < r , 否 则 会 死 循 环 。 实数二分循环条件不能判\ l<r,否则会死循环。 实数二分循环条件不能判 l<r,否则会死循环。
补充:
在 求 二 分 左 右 端 点 的 极 限 m l x 和 m r x 时 , 由 于 存 在 所 有 点 的 横 坐 标 相 等 的 情 况 , 所 以 m l x 初 始 值 不 能 大 于 m r x , 否 则 会 出 现 二 者 相 等 的 情 况 。 在求二分左右端点的极限mlx和mrx时,由于存在所有点的横坐标相等的情况,所以mlx初始值不能大于mrx,\\否则会出现二者相等的情况。 在求二分左右端点的极限mlx和mrx时,由于存在所有点的横坐标相等的情况,所以mlx初始值不能大于mrx,否则会出现二者相等的情况。
事 实 上 不 求 m l x 和 m r x , 直 接 将 二 分 端 点 l 和 r 设 为 数 据 范 围 的 端 点 l = − 10000 , r = 10000 应 当 是 最 简 洁 方 便 的 。 事实上不求mlx和mrx,直接将二分端点l和r设为数据范围的端点l=-10000,r=10000应当是最简洁方便的。 事实上不求mlx和mrx,直接将二分端点l和r设为数据范围的端点l=−10000,r=10000应当是最简洁方便的。