Description
著名的手机网络运营商Totalphone 修建了若干基站收发台,以用于把信号网络覆盖一条新建的高速公路。因为Totalphone 的程序员总是很马虎的,所以,基站的传功功率不能独立设置,只能将所有新基站的功率设置为一个相同的值。为了让能源的消耗尽量少,公司希望知道公路中任意点到最近基站距离的最大值。
Input
输入的第一行包括两个整数N(1<=N<=10^6)和L(1<=L<=10^9)分别表示基站收发台的数量和高速公路的长度。接下来N行,每行包含一对整数xi,yi(-10^9<=xi,yi<=10^9)描述一个基站的坐标。所有给出的点都互不相同。点按照x坐标不下降排列。如果两个点的x坐标相同,那么它们之间按照y坐标的升序排列。
高速公路是一条从(0,0) 到(L,0) 的直线线段。
Output
输出的唯一一行包含单独一个数字——任意点到最近基站距离的最大值。你的输出被认为是正确的仅当它与精确结果的误差不大于10^-3。
Sample Input
2 10
0 0
11 1
Sample Output
5.545455
Data Constraint
总值25 分的数据满足N<=5000
总值50 分的数据满足N<=1000000。
假设所有n个点x坐标均不相同。如果有两个点x坐标相同,那么显然只需要保留y坐标绝对值较小的一个即可。
用这个方法缩点以后二分可以拿93分。。
但是出题人构造了数据来卡。。
按x坐标的顺序从小到大扫描n个整点,用一个栈保存可能成为最近点的整点。同时维护栈中两点连线段中垂线与给出线段交点x坐标单调递增。每当加入一个点前,判断是否破坏了栈的单调性,如果不满足单调性则弹出栈顶元素直到单调性被满足,再将新点加入栈顶。最后答案即为线段的端点以及所有中垂线交点与他们最近点的距离的最大值。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fd(i,a,b) for (int i=a;i>=b;i--)
#define sqr(x)((x)*(x))
using namespace std;
typedef long long LL;
typedef pair<int,int>nod;
typedef pair<double,double>node;
const int N=1000005;
const double INF=1e100,eps=1e-10;
node a[N],b[N],c[N];
int m,len,n,top,q[N];
double ans=0.0;
int read()
{
char c; while (c=getchar(),(c !='-')&&(c<'0'|| c>'9'));
bool neg=(c=='-'); int ret=neg ? 0 : c-48;
while (c=getchar(),c>='0'&& c<='9') ret=ret*10+c-48;
return neg ?-ret : ret;
}
double solve(node *a,int n)
{
if (!n) return INF;
return ans;
}
int main()
{
freopen("mobile.in","r",stdin),freopen("mobile.out","w",stdout);
scanf("%d%d",&m,&len);
fo(i,1,m)
a[i].first=read(),a[i].second=read();
fo(i,1,m)
{
int j=i;
while (j<=m&&a[i].first==a[j].first&&a[j].second<0)++j;
c[++n].first=a[i].first,c[n].second=INF;
if (i<j) c[n].second=-a[j-1].second;
if (j<=m&&a[i].first==a[j].first) c[n].second=min(c[n].second,a[j].second);
while (j<=m&&a[i].first==a[j].first)++j;
i=j-1;
}
fo(i,1,n) a[i]=c[i];
b[1]=make_pair(-INF,INF);
q[top=1]=1;
fo(i,2,n)
{
while (top)
{
double aa=a[i].first-a[q[top]].first,bb=a[i].second-a[q[top]].second;
double mx=0.5 *(a[i].first+a[q[top]].first),mn=0.5 *(a[i].second+a[q[top]].second);
double k=(mx*aa+mn*bb)/aa;
if (k>b[q[top]].first)
{
b[q[top]].second=b[i].first=k,b[i].second=INF;
q[++top]=i;
break;
} else top --;
}
}
ans=0.0;
fo(i,1,top)
{
int x=q[i];
double l=max(0.0,b[x].first),r=min((double)len,b[x].second);
if (l<r)
{
double now=max(sqr(a[x].first-l),sqr(a[x].first-r))+sqr(a[x].second);
if (now>ans)
ans=now;
}
}
printf("%.5f\n",sqrt(ans));
return 0;
}