传送门
Analysis
比较容易想到 把原题转化为判定问题 比如说 对于一个ans 对每个点画圆 判断是否覆盖整条线段
显然 二分是过不了的 邪恶的出题人做了很多事情 比如说 500ms SPJ 假装不卡精度 100个数据点
于是 草稿纸上就有了下面这张图 可以看到 这些园之间有交集 当然是希望两两交集尽量小的 于是可以两两考虑极限下 两者交集最小的值 然后随便搞搞好了
具体实现中 可以使用中垂线的性质 拿中垂线求个交点一类的 至于如何求交点的话 db perbis(Dot x,Dot y) {return ((sqr(x.x) - sqr(y.x) + sqr(x.y) - sqr(y.y)) / (2 * (x.x - y.x)));} 不算太难 但很难一步想到中垂线
Code
using namespace std;
typedef long long ll;
typedef double db;
const ll N =
1001000,NM =
1e15,Prec =
1e4;
struct Dot{
db
x,
y;
Dot(db
x_ =
0,db
y_ =
0){
x =
x_,
y =
y_;}
}a[N];
ll n,L,
m;
db tmp,ans;
ll sta[N],hd,tl;
db
read(db &n)
{
char ch=
' ';db
q=
0,w=
1;
for(;(ch!=
'-')&&((ch<
'0')||(ch>
'9'));ch=getchar());
if(ch==
'-')w=-
1,ch=getchar();
for(;ch>=
'0' && ch<=
'9';ch=getchar())
q=
q*10+ch-
48;n=
q*w;
return n;
}
inline db
sqr(db x) {
return ((
x)
*(x));}
inline db max(db
x,db
y) {
return (((
x)>(
y))?(
x):(
y));}
inline db min(db
x,db
y) {
return (((
x)<(
y))?(
x):(
y));}
db perbis(Dot
x,Dot
y) {
return ((
sqr(x.x) -
sqr(y.x) +
sqr(x.y) -
sqr(y.y)) / (
2 * (
x.
x -
y.
x)));}
int main()
{
freopen(
"mobile.in",
"r",stdin);
freopen(
"mobile.out",
"w",stdout);
scanf(
"%lld%lld", &n, &L);
//a[
m =
1] = Dot(
0,
0);
fo(i,
1,n)
{
db
x,
y;
read(
x),
read(
y);
if (
x != a[
m].
x) a[++
m] = Dot(
x,
y);
else
if (
x == a[
m].
x && (
abs(
y) <
abs(a[
m].
y))) a[
m] = Dot(
x,
y);
}
//a[++
m] = Dot(L,
0);
n =
m;
tmp = oo * oo;
fo(i,
1,n)
if (
sqr(a[i].x) +
sqr(a[i].y) < tmp * tmp)
tmp =
sqrt(
sqr(a[i].x) +
sqr(a[i].y));
ans = tmp,
tmp = oo * oo;
fo(i,
1,n)
if (
sqr(a[i].x - L) +
sqr(a[i].y) < tmp * tmp)
tmp =
sqrt(
sqr(a[i].x - L) +
sqr(a[i].y));
ans = max(ans,tmp);
sta[
1] = tl = hd =
1;
fo(i,
2,n)
{
while (hd < tl && perbis(a[sta[hd]],a[sta[hd +
1]]) <
0) ++ hd;
while (hd < tl && perbis(a[sta[tl]],a[sta[tl -
1]]) > perbis(a[i],a[sta[tl]])) -- tl;
sta[++ tl] = i;
}
fo(i,hd,tl -
1)
{
db p = perbis(a[sta[i]],a[sta[i +
1]]);
if (p > L)
break;
tmp =
sqrt(
sqr(a[sta[i]].x - p) +
sqr(a[sta[i]].y));
ans = max(ans,tmp);
}
printf(
"%lf", ans);
}
转载请注明原文地址: https://ju.6miu.com/read-6005.html