【CF887E】Little Brother 二分+几何

【CF887E】Little Brother

题意:给你n个圆和一条线段,保证圆和圆、圆和线段所在直线不相交,不相切,不包含。求一个过线段两端点的圆,满足不和任何圆相交(可以相切、包含)。问圆的最小半径。

n<=100000

题解:比较显然的二分题。由于新圆的半径一定在线段的中垂线上,且距离越远半径越大。那么问题就变成了最小化半径到线段的距离。

不难发现,对于每个圆来说,如果新圆不和它相交,那么半径所在的区域会被限定在$(-\infty,a]\bigcup[b,\infty)$里。a和b我们可以通过二分求得。最后用扫描线统计出所有合法的半径区间,并更新答案即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=100010;
struct point
{
	double x,y;
	point() {}
	point(double a,double b) {x=a,y=b;}
	point operator + (const point &a) const {return point(x+a.x,y+a.y);}
	point operator - (const point &a) const {return point(x-a.x,y-a.y);}
	point operator * (const double &a) const {return point(x*a,y*a);}
	double operator * (const point &a) const {return x*a.y-y*a.x;}
}A,B,P,C,D,O,K,K1;
int n,m,sum;
double R,ans;
struct node
{
	double x;	int k;
	node() {}
	node(double a,int b) {x=a,k=b;}
}q[maxn<<1];
inline double dis(point a) {return sqrt(a.x*a.x+a.y*a.y);}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)	f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+(gc^‘0‘),gc=getchar();
	return ret*f;
}
bool cmp(const node &a,const node &b)
{
	return a.x<b.x;
}
int main()
{
	double l,r,mid;
	A.x=rd(),A.y=rd(),B.x=rd(),B.y=rd(),n=rd(),C=(A+B)*0.5,K=B-A;
	K=K*(1.0/dis(K)),K1=point(-K.y,K.x);
	int i,j,flag;
	for(i=1;i<=n;i++)
	{
		P.x=rd(),P.y=rd(),R=rd();
		flag=((P-A)*(B-P)>0);
		l=-1e12,r=1e12;
		for(j=1;j<=80;j++)
		{
			mid=(l+r)/2,O=C+(K1*mid);
			if((dis(P-O)>dis(A-O)+R)^flag)	l=mid;
			else	r=mid;
		}
		q[++m]=node(l,flag?-1:1);
		l=-1e12,r=1e12;
		for(j=1;j<=80;j++)
		{
			mid=(l+r)/2,O=C+(K1*mid);
			if((dis(A-O)>dis(P-O)+R)^flag)	r=mid;
			else	l=mid;
		}
		q[++m]=node(r,flag?1:-1);
	}
	q[++m]=node(1e12,0),q[++m]=node(-1e12,0),q[++m]=node(0,0);
	sort(q+1,q+m+1,cmp);
	ans=1e12;
	for(flag=0,i=1;i<=m;i++)
	{
		if(!sum)	flag=1,ans=min(ans,fabs(q[i].x));
		sum+=q[i].k;
		if(!sum)	flag=1,ans=min(ans,fabs(q[i].x));
	}
	if(!flag)	puts("-1");
	else	O=C+(K1*ans),printf("%.10lf",dis(A-O));
	return 0;
}//2 4 7 13 3 3 0 1 12 4 2 -4 14 2
时间: 2024-10-10 01:07:13

【CF887E】Little Brother 二分+几何的相关文章

uva 11978 - Fukushima Nuclear Blast(二分+几何)

题目链接:uva 11978 - Fukushima Nuclear Blast 二分,圆和多边形面积交.将多边形拆成n份三角形(每两点与圆心构成),计算有向面积.每个三角形和圆的面积分四类讨论. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using namespace std; const double

Incircle and Circumcircle(二分+几何)浙大月赛zoj3806(详解版)图

Incircle and Circumcircle Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge A triangle is one the basic shapes in geometry. It's a polygon with three vertices and three sides which are line segments. A triangle with vertices A, B, C is denot

hdu 4033 二分几何

参考:http://blog.csdn.net/libin56842/article/details/26618129 题意:给一个正多边形内点到其他顶点的距离(逆时针给出),求正多边形的边长 二分多边形的边长 根据余弦定理求出A的角度,之后求出所有角度,加起来是否为360,小于则扩大,大于则缩小边 Sample Input 2 3 3.0 4.0 5.0 3 1.0 2.0 3.0 Sample Output Case 1: 6.766 Case 2: impossible 1 #includ

【CF744D】Hongcow Draws a Circle 二分+几何

[CF744D]Hongcow Draws a Circle 题意:给你平面上n个红点和m个蓝点,求一个最大的圆,满足圆内不存在蓝点,且至少包含一个红点. $n,m\le 10^3$ 题解:我们先不考虑半径为inf的情况.显然所求的圆一定是要与某个蓝点相切的.我们可以先枚举这个蓝点,然后二分答案.当半径已知.一个点固定时,圆的可能位置只能是绕着一个点旋转得到的结果,其余的所有点都对应着极角上的一段区间,我们可以将这些区间排序,采用扫描线,看一下是否存在一段区间包含红点且不包含蓝点即可. 但是如果

poj 1905Expanding Rods

1 /* 2 二分 + 几何 3 弧长L, 圆半径R, 弧度 q, L=R*q; 4 二分: 弧度(0~PI) 或者 高度(L/2~L) 5 */ 6 #include<cstdio> 7 #include<iostream> 8 #include<cmath> 9 using namespace std; 10 const double PI = acos(-1.0); 11 double L, L1, T, C, R, Q; 12 13 int main(){ 14

CUGBACM_Summer_Tranning3 2013长沙现场赛(二分+bfs模拟+DP+几何)

A题:二分 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4791 用lower_bound可以轻松解决,不过比赛的时候逗逼了. 刚开始没有预处理,所以队友给出一组数据的时候没通过,然后一时紧张又想不出什么好的解决办法,所以就没再继续敲代码.实在有点可惜了. #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #includ

uva 1463 - Largest Empty Circle on a Segment(二分+三分+几何)

题目链接:uva 1463 - Largest Empty Circle on a Segment 二分半径,对于每个半径,用三分求出线段到线段的最短距离,根据最短距离可以确定当前R下每条线段在[0,L]上的可行区间,存在一个点被可行区间覆盖n次. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using n

简单几何(半平面交+二分) LA 3890 Most Distant Point from the Sea

题目传送门 题意:凸多边形的小岛在海里,问岛上的点到海最远的距离. 分析:训练指南P279,二分答案,然后整个多边形往内部收缩,如果半平面交非空,那么这些点构成半平面,存在满足的点. /************************************************ * Author :Running_Time * Created Time :2015/11/10 星期二 14:16:17 * File Name :LA_3890.cpp ********************

[CF989D]A Shade of Moonlight:几何+二分答案+玄学的思路

题意: 一条一维数轴上,有n个左端点为xi,长度l的区间.以向右为正方向,第i个区间的移动速度为vi+w(vi=1或-1,|w|<=wmax,所有区间的w相同). 输入n,l,wmax,vi. 输出无序数对(i,j)的个数,使第i个区间和第j个区间有一个合法的w的取值,在某一时刻同时覆盖原点(不包括区间左.右边界). (n<=1e5) 思路: 因为w的取值是不定的,所以可以看成是每个区间以vi的速度运动,而原点以-w的速度运动. 很容易画出一个时间-位置图像(横轴位置,纵轴时间),其中橙色区域