码迷,mamicode.com
首页 > 其他好文 > 详细

[CF1059]Nature Reserve

时间:2020-07-20 10:41:42      阅读:56      评论:0      收藏:0      [点我收藏+]

标签:时间   复杂   iostream   sig   包含   str   names   inline   log   

题目

传送门

题解

一道十分巧妙的二分题 然而精度要求较高

首先考虑无解情况——有某两个点在 \(x\) 轴的上下方,此时输出 -1

否则,考虑二分这个圆的半径 \(r\),那么这个圆心所在的位置一定是一条直线 \(y=r\)(此处我们将所有的点都转移到 \(x\) 轴上方,故不考虑正负号问题),然后,根据 \(r\) 和所有点的位置,我们得以用勾股定理求得,要包含点 \((x_i,y_i)\) 的合法圆心的 \(x\) 坐标一定在 \([x_i-\sqrt{r^2+(y_i-r)^2},x_i+\sqrt{r^2+(y_i-r)^2}]\),然后我们将所有的区间取并集,如果最后的集合为空,说明 \(r\) 过小,不为空则继续往小二分。

时间复杂度 \(\mathcal O(n\log{1e18})\)

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
using namespace std;

const double eps=1e-8;
const int MAXN=1e5;

struct node{double x,y;}p[MAXN+5];

int n,pos;

double L,R;

template<class T>const T fab(const T a){return a<0?-a:a;}

inline void Init(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
    	scanf("%lf %lf",&p[i].x,&p[i].y);
        if((p[i].y<0 && pos==1) || (p[i].y>0 && pos==-1)){
            puts("-1");
            exit(0);
        }else pos=(p[i].y<0)?-1:1,p[i].y=fab(p[i].y);
    }
}

inline bool Check(const double x){
	double l=-1e18,r=1e18,len;
	for(int i=1;i<=n;++i){
		if(p[i].y>2*x)return false;
		len=sqrt(p[i].y)*sqrt(2*x-p[i].y);
		l=max(l,p[i].x-len);
		r=min(r,p[i].x+len);
	}return l<r;
}

inline void Bisearch(){
	double mid,ans;
	R=1e18;
	for(int times=1;times<=1000;++times){
//		printf("Now L == %f, R == %f\n",L,R);
		mid=(L+R)/2;
		if(Check(mid))ans=R=mid;
		else L=mid;
	}
	printf("%f\n",ans);
}

signed main(){
    Init();
    Bisearch();
    return 0;
}
/*
2
-10000000 1
10000000 1
*/

[CF1059]Nature Reserve

标签:时间   复杂   iostream   sig   包含   str   names   inline   log   

原文地址:https://www.cnblogs.com/Arextre/p/13343125.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!