CF1446F Line Distance

若干个点,两两间连线。问和原点距离第(k)大的直线,到原点距离是多少。

(nle 10^5)


显然二分,然后就是计数。

结论:两个点(A,B)分别引切线到圆,分别记切点为(A_0,A_1,B_0,B_1)。如果(A_0A_1,B_0B_1)相交,那么(AB)与圆相离。

画画图即可证明。

离散化之后树状数组即可。注意判断一下点在圆内的情况。


using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cassert>
#define N 100005
#define ll long long
const double PI=acos(-1);
int n;
ll k;
struct DOT{double x,y;} d[N];
double sqr(double x){return x*x;}
void adjust(double &t){
	t-=int(t/(2*PI))*(2*PI);
	if (t<-1e-10) t+=2*PI;
}
int m;
DOT q[N];
int nv;
double *p[N*2];
bool cmpp(double *x,double *y){return *x<*y;}
int t[N*2];
void add(int x){
	for (;x<=nv;x+=x&-x)
		t[x]++;
}
int query(int x){
	int r=0;
	for (;x;x-=x&-x)
		r+=t[x];
	return r;
}
void init(int n){
	sort(p+1,p+n+1,cmpp);
	nv=0;
	double last=19260817;
	for (int i=1;i<=n;++i){
		if (*p[i]!=last)
			last=*p[i],++nv;
		*p[i]=nv;
	}
	memset(t,0,sizeof(int)*(nv+1));
}
bool cmpq(DOT a,DOT b){return a.y<b.y;}
void insert(double l,double r){
	adjust(l);
	adjust(r);
	if (l>r) swap(l,r);
	q[++m]={l,r};
}
ll res;
ll calc(double r){
	m=0;
	for (int i=1;i<=n;++i){
		double l=sqrt(sqr(d[i].x)+sqr(d[i].y));
		if (l<=r) continue;
		double b=acos(r/l);
		double a=atan2(d[i].y,d[i].x);
		insert(a-b,a+b);
	}
	res=(ll)(n-m)*m+(ll)(n-m)*(n-m-1)/2;
	sort(q+1,q+m+1,cmpq);
	for (int i=1;i<=m;++i)
		p[i]=&q[i].x,p[m+i]=&q[i].y;
//	for (int i=1;i<=m;++i)
//		printf("%lf %lf
",q[i].x,q[i].y);
	init(m*2);
//	for (int i=1;i<=m;++i)
//		printf("%d %d
",(int)q[i].x,(int)q[i].y);
	for (int i=m;i>=1;--i){
		res+=query((int)q[i].x)+(m-i)-query((int)q[i].y);
		add((int)q[i].x);
	}
	return res;
}
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	scanf("%d%lld",&n,&k);
	for (int i=1;i<=n;++i)
		scanf("%lf%lf",&d[i].x,&d[i].y);
//	printf("%lld
",calc(1));
//	return 0;
//	return 0;
	double l=0,r=2e4;
	while (r-l>1e-9){
		double mid=(l+r)/2;
//		printf("%lld
",calc(mid));
		if (calc(mid)>=k)
			r=mid;
		else
			l=mid;
	}
	printf("%.8lf
",l);
	return 0;
}
原文地址:https://www.cnblogs.com/jz-597/p/14006550.html