正题

题目链接:https://www.luogu.com.cn/problem/CF1446F


题目大意

给出\(n\)个点,求所有点对构成的直线中与原点距离第\(k\)小的距离

\(2\leq n\leq 10^5,1\leq k\leq \frac{n(n-1)}{2}\)


解题思路

二分还是挺显然的,考虑二分了之后怎么判断一个距离以内的直线数量

两个点对之间的直线在原点距离\(d\)以内,也就是这条直线经过原点为中心半径为\(d\)的圆。换一种理解,也就是如果有这个圆那么这两个点对之间无法相互看见。

现在问题变为了求有多少个点对之间无法相互看见,给张官方题解的图片就挺容易理解的



也就是说我们对于每个点找到它与圆的两个切点之间在圆上构成的一个区间。

如果两个点的区间有交集那么他们就可以相互看见。

现在问题就变为了求有多少对区间有交。

这个直接用树状数组统计就好了。

环的话直接断开,跨越了环的就取反。


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
const ll N=2e5+10;
double eps=1e-8,Pi=acos(-1);
ll n,k,cnt,m,t[N],p[N],l[N],r[N];
double a[N],b[N],c[N],L[N],R[N];
bool v[N];
void Change(ll x,ll val){
while(x<=cnt){
t[x]+=val;
x+=lowbit(x);
}
return;
}
ll Ask(ll x){
ll ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
bool cmp(ll x,ll y)
{return l[x]<l[y];}
ll check(double d){
cnt=0;m=0;
for(ll i=1;i<=n;i++)v[i]=0;
for(ll i=1;i<=n;i++){
double dis=sqrt(a[i]*a[i]+b[i]*b[i]);
if(dis-d<eps){v[i]=1;continue;}
double ang=atan2(b[i],a[i]),ta=acos(d/dis);
L[i]=ang-ta;R[i]=ang+ta;
if(L[i]<-Pi)L[i]+=2*Pi;
if(R[i]>Pi)R[i]-=2*Pi;
if(L[i]>R[i])swap(L[i],R[i]);
c[++cnt]=L[i];c[++cnt]=R[i];
}
sort(c+1,c+1+cnt);
for(ll i=1;i<=n;i++){
if(v[i])continue;p[++m]=i;
l[i]=lower_bound(c+1,c+1+cnt,L[i])-c;
r[i]=lower_bound(c+1,c+1+cnt,R[i])-c;
}
memset(t,0,sizeof(t));
sort(p+1,p+1+m,cmp);
ll ans=n*(n-1)/2;
for(ll i=1;i<=m;i++){
ll x=p[i];
ans-=Ask(r[x])-Ask(l[x]-1);
Change(r[x],1);
}
return ans;
}
signed main()
{
scanf("%lld%lld",&n,&k);
for(ll i=1;i<=n;i++)
scanf("%lf%lf",&a[i],&b[i]);
double l=0,r=20000;
while(r-l>=eps){
double mid=(l+r)/2.0;
if(check(mid)<k)l=mid;
else r=mid;
}
printf("%.10lf",l);
return 0;
}

CF1446F-Line Distance【计算几何,树状数组,二分】的更多相关文章

  1. POJ 2182 Lost Cows 【树状数组+二分】

    题目链接:http://poj.org/problem?id=2182 Lost Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  2. POJ 2828 Buy Tickets (线段树 or 树状数组+二分)

    题目链接:http://poj.org/problem?id=2828 题意就是给你n个人,然后每个人按顺序插队,问你最终的顺序是怎么样的. 反过来做就很容易了,从最后一个人开始推,最后一个人位置很容 ...

  3. TZOJ 4602 高桥和低桥(二分或树状数组+二分)

    描述 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算“淹了两次”.举 ...

  4. 树状数组+二分||线段树 HDOJ 5493 Queue

    题目传送门 题意:已知每个人的独一无二的身高以及排在他前面或者后面比他高的人数,问身高字典序最小的排法 分析:首先对身高从矮到高排序,那么可以知道每个人有多少人的身高比他高,那么取较小值(k[i], ...

  5. P2161 [SHOI2009]会场预约[线段树/树状数组+二分/STL]

    题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...

  6. The Stream of Corning 2( 权值线段树/(树状数组+二分) )

    题意: 有两种操作:1.在[l,r]上插入一条值为val的线段 2.问p位置上值第k小的线段的值(是否存在) 特别的,询问的时候l和p合起来是一个递增序列 1<=l,r<=1e9:1< ...

  7. 牛客多校第3场 J 思维+树状数组+二分

    牛客多校第3场 J 思维+树状数组+二分 传送门:https://ac.nowcoder.com/acm/contest/883/J 题意: 给你q个询问,和一个队列容量f 询问有两种操作: 0.访问 ...

  8. ZOJ 3157 Weapon --计算几何+树状数组

    题意:给一些直线,问这些直线在直线x=L,x=R之间有多少个交点. 讲解见此文:http://blog.sina.com.cn/s/blog_778e7c6e0100q64a.html 首先将直线分别 ...

  9. HDU 6278 - Just h-index - [莫队算法+树状数组+二分][2018JSCPC江苏省赛C题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6278 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...

随机推荐

  1. C# 获取计算机的硬件、操作系统信息

    C# 获取计算机的硬件.操作系统信息   获得信息的命名空间是:System.Management 创建ManagementObjectSearcher对象获取相关信息 eg: using Syste ...

  2. Qt中子窗口关闭之后,立即释放资源的方法

    用Qt做界面的时候,很多时候都会遇见点击一个按钮弹出一个新的窗口的功能.我在刚开始做这个功能的时候,直接是点击一次按钮就new一个新的窗口,每次都只是将子窗口关闭而已,并没有去释放子窗口的资源,这样就 ...

  3. 深入浅出Mybatis系列(七)---TypeHandler简介

    无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型.Mybatis默认 ...

  4. Jmeter教程 录制脚本

    Jmeter 录制脚本 Jmeter中有2种方法可以录制脚本.  不过我个人非常不推荐录制脚本,录制的脚本混乱,需要再次加工才能使用. 像我这么精通HTTP协议的人. 一直都是使用Fiddler来抓包 ...

  5. URL的加密解密方法

    package day11.about_url_encoder; import java.io.UnsupportedEncodingException; import java.net.URLDec ...

  6. 作用域 作用域链 闭包 思想 JS/C++比较

    首先,我说的比较是指JS中这种思想/实现方式与C++编译原理中思想/实现方式的比较 参考链接:(比较易懂的介绍,我主要写个人理解) 作用域链: http://www.cnblogs.com/dolph ...

  7. TCP协议中的TIME_WAIT详细说明

    文章目录 4.3设置TIME_WAIT状态的目的 4.3.1 实现TCP全双工连接的关闭 4.3.2 使过时的重复报文段失效 4.3.3 TIME_WAIT状态的自结束 4.3.4 TIME_WAIT ...

  8. Linux内核中的Workqueue机制分析

    1. 什么是workqueue Linux中的workqueue(工作队列)主要是为了简化在内核创建线程而设计的.通过相应的工作队列接口,可以使开发人员只关心与特定功能相关的处理流程,而不必关心内核线 ...

  9. 【第八篇】- Git 查看提交历史之Spring Cloud直播商城 b2b2c电子商务技术总结

    ​ Git 查看提交历史 Git 提交历史一般常用两个命令: git log 在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log 命令查看. 针对 ...

  10. 【第十四篇】- Maven 自动化构建之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 自动化构建 自动化构建定义了这样一种场景: 在一个项目成功构建完成后,其相关的依赖工程即开始构建,这样可以保证其依赖项目的稳定. 比如一个团队正在开发一个项目 bus-core-api, ...