Codeforces - D. Nature Reserve

题目链接:Codeforces - D. Nature Reserve


首先肯定二分半径。

然后我们可以发现,半径确定之后,圆心肯定在一条直线上面。

然后我们可以发现对于每个点,都能找到满足覆盖这个点的区间,问题就转化为判断区间是否有交集。

AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
const int N=1e5+10;
const double eps=1e-8;
long double x[N],y[N],l,r=1e18,mi=1e9,mx;	int n,cnt; set<int> s;
inline int check(double mid){
	long double cl=-1e18,cr=1e18;
	for(int i=1;i<=n;i++){
		if(y[i]>2*mid)	return 0;
		long double p=sqrt(2.0*y[i]*mid-y[i]*y[i]);
		long double ql=x[i]-p,qr=x[i]+p;
		cl=max(cl,ql),cr=min(qr,cr);
		if(cl>cr)	return 0;
	}
	return 1;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>y[i],mi=min(mi,y[i]),mx=max(mx,y[i]);
		if(fabs(y[i])<eps)	cnt++;	s.insert((int)(x[i]));
		y[i]=fabs(y[i]);
	}	
	if((mx>0&&mi<0)||cnt>1)	return puts("-1"),0;
	if(s.size()==1){
		long double mx=-1e18;
		for(int i=1;i<=n;i++)	mx=max(mx,y[i]);
		return printf("%.10Lf\n",mx/2),0;
	}
	for(int i=1;i<=150;i++){
		long double mid=(l+r)/2;
		if(check(mid))	r=mid;
		else	l=mid;
	}
	printf("%.10Lf\n",l);
	return 0;
}

你可能感兴趣的:(Codeforces,二分,计算几何)