[CodeForces]1059D Nature Reserve

大意:给你一个平面上N(N<=100000)个点,问相切于x轴的圆,将所有的点都覆盖的最小半径是多少。

 

计算几何???Div2的D题就考计算几何???某人昨天上课才和我们说这种计算几何题看见就溜。。。。

打完比赛才发现好像并不用计算几何,实则是一个二分答案的水题。。

发现如果点在x轴两侧就肯定不行,所以我们把所有的点都挪到一侧。

我们二分一个半径,然后发现因为圆相切于x轴,那么这个圆的圆心一定在y=r的直线上移动。

对于所有的点,它可以被如图的线段AC上的点覆盖,点在AC下方也同理。(终于有个图是我自己画的了。。。)

然后发现圆心的取值就在xi±√(R2-(R-yi)2)之间。

所以说把每个点的可取圆心的点的集合的交算出来,看看是不是空集,不是空集就可行。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
const double eps=1e-8;
int n;
struct Node {int x,y;}node[100005];
bool flag;
bool ck(double mid) {
    double l=-1e18,r=1e18;
    for(int i=1;i<=n;i++) {
        if(node[i].y>mid+mid) return 0;
        double range=sqrt(node[i].y*(2*mid-node[i].y));
        l=max(l,node[i].x-range);r=min(r,node[i].x+range);
    }
    return (l-r+eps)<=0;
}
int main() {
    scanf("%d",&n);
    scanf("%d%d",&node[1].x,&node[1].y);
    if(node[1].y<0) flag=1;node[1].y=abs(node[1].y);
    for(int i=2;i<=n;i++) {
        scanf("%d%d",&node[i].x,&node[i].y);
        if(flag&&node[i].y>0){puts("-1") ;return 0;}
        if(flag==false && node[i].y<0) {puts("-1");return 0;}
        node[i].y=abs(node[i].y);
    }
    double l=0,r=1e18;int cnt=300;
    while(cnt--) {
        double mid=(l+r)/2;
        if(ck(mid)) r=mid;
        else l=mid;
    }
    printf("%lf",l);
}
Nature Reserve

 

posted @ 2018-10-06 20:28  SWHsz  阅读(339)  评论(0编辑  收藏  举报