【CF744D】Hongcow Draws a Circle

题意:给你平面上n个红点和m个蓝点,求一个最大的圆,满足圆内不存在蓝点,且至少包含一个红点。

$n,m\le 10^3$

题解:我们先不考虑半径为inf的情况。显然所求的圆一定是要与某个蓝点相切的。我们可以先枚举这个蓝点,然后二分答案。当半径已知、一个点固定时,圆的可能位置只能是绕着一个点旋转得到的结果,其余的所有点都对应着极角上的一段区间,我们可以将这些区间排序,采用扫描线,看一下是否存在一段区间包含红点且不包含蓝点即可。

但是如果你仔细分析的话你会发现这样的二分是不满足单调性的。不过如果我们一开始不光枚举蓝点,还枚举所有红点,一起进行二分,这样就满足单调性了。

直接做的复杂度是$O(n\log ^2 n)$,会TLE,看了标程加了一些神优化才过~具体见代码。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define pi acos(-1.0)
using namespace std;
typedef long double db;
const db eps=1e-12;
const int maxn=1010;
struct point
{
db x,y;
point() {}
point(db a,db 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);}
db operator * (const point &a) const {return x*a.y-y*a.x;}
point operator * (const db &a) const {return point(x*a,y*a);}
}p[maxn<<1];
struct line
{
point p,v;
line() {}
line(point a,point b) {p=a,v=b;}
};
struct node
{
db x;
int k;
node() {}
node(double a,int b) {x=a,k=b;}
}q[maxn<<3];
int n,m,tot;
inline db dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
db getrange(point a,point b,db R)
{
db d=dis(a,b)/2;
return acos(d/R);
}
bool cmp(const node &a,const node &b) {return a.x<b.x;}
inline bool solve(int x,db R)
{
int i;
tot=0;
if(x<=n) q[++tot]=node(-pi,1),q[++tot]=node(pi,-1);
else
{
for(i=1;i<=n;i++)
{
if(dis(p[i],p[x])>R+R-eps) continue;
db a=getrange(p[x],p[i],R),b=atan2(p[i].y-p[x].y,p[i].x-p[x].x);
db c=b-a,d=b+a;
if(c<-pi) c+=2*pi;
if(d>pi) d-=2*pi;
if(c<d) q[++tot]=node(c,1),q[++tot]=node(d,-1);
else q[++tot]=node(-pi,1),q[++tot]=node(d,-1),q[++tot]=node(c,1),q[++tot]=node(pi,-1);
}
}
for(i=n+1;i<=n+m;i++)
{
if(dis(p[i],p[x])>R+R-eps) continue;
db a=getrange(p[x],p[i],R),b=atan2(p[i].y-p[x].y,p[i].x-p[x].x);
db c=b-a,d=b+a;
if(c<-pi) c+=2*pi;
if(d>pi) d-=2*pi;
if(c<d) q[++tot]=node(c,-10000),q[++tot]=node(d,10000);
else q[++tot]=node(-pi,-10000),q[++tot]=node(d,10000),q[++tot]=node(c,-10000),q[++tot]=node(pi,10000);
}
sort(q+1,q+tot+1,cmp);
int tmp=0;
for(i=1;i<=tot;i++)
{
if(tmp>0&&i!=1&&q[i].x>q[i-1].x+eps) return 1;
tmp+=q[i].k;
}
return 0;
}
inline bool check(db mid)
{
for(int i=1;i<=n+m;i++) if(solve(i,mid)) return 1;
return 0;
}
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;
}
int main()
{
n=rd(),m=rd();
if(m==1)
{
puts("-1");
return 0;
}
int i;
for(i=1;i<=n;i++) p[i].x=rd(),p[i].y=rd();
random_shuffle(p+1,p+n+1);
for(i=1;i<=m;i++) p[i+n].x=rd(),p[i+n].y=rd();
random_shuffle(p+n+1,p+m+1);
db l=0,r,mid;
for(i=1;i<=n+m;i++) if(solve(i,l)) //神优化
{
r=1e9;
while(r-l>1e-5)
{
mid=(l+r)/2;
if(solve(i,mid)) l=mid;
else r=mid;
}
}
if(l>1e9-1) puts("-1");
else printf("%.18Lf",l);
return 0;
}

【CF744D】Hongcow Draws a Circle 二分+几何的更多相关文章

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

    Incircle and Circumcircle Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge A triangle is o ...

  2. hdu 4033 二分几何

    参考:http://blog.csdn.net/libin56842/article/details/26618129 题意:给一个正多边形内点到其他顶点的距离(逆时针给出),求正多边形的边长 二分多 ...

  3. 二分法 (UVA10668 Expanding Rods)(二分+几何)

    转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1301845324 大致题意: 一根两端固定在两面墙上的杆 受热弯曲后变弯曲.求前后两个状态 ...

  4. 【CF887E】Little Brother 二分+几何

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

  5. Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) A B C D 暴力 水 二分 几何

    A. Vicious Keyboard time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  6. 【BZOJ3007】拯救小云公主 二分+几何+对偶图

    [BZOJ3007]拯救小云公主 Description     英雄又即将踏上拯救公主的道路……     这次的拯救目标是——爱和正义的小云公主.     英雄来到boss的洞穴门口,他一下子就懵了 ...

  7. POJ 1905 题解(二分+几何)

    题面 传送门 分析 如图:已知AB=L,弧AB=L(1+nC)" role="presentation" style="position: relative;& ...

  8. POJ2242 The Circumference of the Circle(几何)

    题目链接. 题目大意: 给定三个点,即一个任意三角形,求外接圆的周长. 分析: 外接圆的半径可以通过公式求得(2*r = a/sinA = b/sinB = c/sinC),然后直接求周长. 注意: ...

  9. ZJOI2018游记Round1

    广告 ZJOI2018Round2游记 All Falls Down 非常感谢学弟学妹们捧场游记虽然这是一篇假游记 ZJOI Round1今天正式落下帷幕.在这过去的三天里遇到了很多朋友,见识了很多有 ...

随机推荐

  1. Java编程思想学习笔记——类的访问权限

    类的访问权限 Java中,访问权限修饰词用于确定库中哪些类对于该库的使用者是可用的. public class Foo{ } 注意点: 每个文件(编译单元)只能有一个public类. public类的 ...

  2. node.js和socket.io实现im

    im——Instant Messaging 即时通讯 基本技术原理 (1)通过IM服务器登陆或注销 (2)用户A通过列表找到B,用户B获得消息并与之交谈 (3)通过IM服务器指引建立与B单独的通讯通道 ...

  3. Linux系统安装workerman,启动wss 服务

    安装workerman其实很简单,只要会简单的linux口令就可以搞定, 这里我给大家演示一下如何安装workerman 进入终端的过程就不用演示了吧... 输入root及密码进入终端后找到站点根目录 ...

  4. 错误 Unable to find vcvarsall.bat 的终极无敌最完美的解决办法

    Windows 上通过 pip 安装 python 包,经常会出现这种错误. 如:pip install pyodbc. 这种错误的简单明了解释就是:python 编译器找不到计算机上面的 VC 编译 ...

  5. oracle自定义类型 示例

    ) ); ---自定义类型传参给存储过程,示例如下: create or replace procedure dropWf is cursor c_tenant is and t.id not in ...

  6. repo_folder

    -- Create table create table REPO_FOLDER ( UUID ) not null, VALID ) not null, CREATE_TIME ) not null ...

  7. IIS------如何安装IIS

    1.打开“控制面板”->“程序”->“打开或关闭Windows功能” 2.如图所示: 3.如图所示: 4.点击确定,配置完成

  8. Java显示指定类型的文件

    文件作为存储数据的单元,会根据数据类型产生很多分类,也就是所谓的文件类型.在对数据文件进行操作时,常常需要根据不同的文件类型来作不同的处理.本实例实现的是读取文件夹指定类型的文件并显示到表格控件中.这 ...

  9. Docker background

    什么是 Docker? Docker 提供了一个可以运行你的应用程序的封套(envelope),或者说容器.它原本是 dotCloud 启动的一个业余项目,并在前些时候开源了.它吸引了大量的关注和讨论 ...

  10. MongoDB的数据模型

    文档的数据模型代表了数据的组织结构,一个好的数据模型能更好的支持应用程序.在MongoDB中,文档有两种数据模型,内嵌(embed)和引用(references). 内嵌 MongoDB的文档是无模式 ...