zoukankan      html  css  js  c++  java
  • CF1446F. Line Distance

    题目大意

    给出n个点,求n(n-1)/2条直线据原点距离中第k小的

    n<=1e5,k<=n(n-1)/2

    题解

    结论题

    首先二分答案,变成判断一条直线AB是否与圆有交

    结论:直线AB与圆有交,当且仅当A的切点连线A1A2和B的切点连线B1B2不相交

    证明感受一下



    所以直接离散化+树状数组即可

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define M_PI 3.14159265358979323846
    #define abs(x) ((x)>0?(x):-(x))
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    #define low(x) ((x)&-(x))
    #define E 0.000000001
    #define ll long long
    //#define file
    using namespace std;
    
    struct type{double x;int id;} b[200001];
    struct Type{int x,y;} c[100001];
    double X[100001],Y[100001],dis[100001],S[100001],L,R,Mid;
    int tr[200001],n,i,j,k,l;
    ll K;
    
    void change(int t,int s) {while (t<=n*2) tr[t]+=s,t+=low(t);}
    int find(int t) {int ans=0; while (t) ans+=tr[t],t-=low(t);return ans;}
    bool cmp(type a,type b) {return a.x<b.x;}
    bool Cmp(Type a,Type b) {return a.x<b.x;}
    bool pd(double r)
    {
    	double s1,s2,ss,s;
    	ll sum=0;
    	
    	l=0;
    	fo(i,1,n)
    	if (dis[i]>r)
    	{
    		s=acos(r/dis[i]);
    		s1=S[i]-s,s2=S[i]+s;
    		if (s1<0) s1+=M_PI*2;
    		if (s2>M_PI*2) s2-=M_PI*2;
    		if (s1>s2) ss=s1,s1=s2,s2=ss;
    		b[++l]={s1,-i},b[++l]={s2,i};
    	}
    	
    	if (l)
    	{
    		fo(i,1,n) c[i]={1,0};
    		sort(b+1,b+l+1,cmp);
    		fo(i,1,l)
    		{
    			if (b[i].id<0) c[-b[i].id].x=i;
    			else c[b[i].id].y=i;
    		}
    		
    		l=0;
    		fo(i,1,n) if (c[i].x<=c[i].y) c[++l]=c[i];
    		sort(c+1,c+l+1,Cmp);
    		memset(tr,0,sizeof(tr));
    		fd(i,l,1)
    		{
    			sum+=find(c[i].y);
    			change(c[i].x,1),change(c[i].y,-1);
    		}
    	}
    	sum=1ll*n*(n-1)/2-sum;
    	return sum>=K;
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF1446F.in","r",stdin);
    	#endif
    	
    	scanf("%d%lld",&n,&K);
    	fo(i,1,n)
    	{
    		scanf("%lf%lf",&X[i],&Y[i]),dis[i]=sqrt(X[i]*X[i]+Y[i]*Y[i]),S[i]=atan2(Y[i],X[i]);
    		if (S[i]<0) S[i]+=M_PI*2;
    	}
    	L=0,R=20000;
    	while (R-L>E)
    	{
    		Mid=(L+R)/2;
    		if (!pd(Mid))
    		L=Mid; else R=Mid;
    	}
    	printf("%.15lf
    ",L);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    浅谈3次登录错误
    JDK一键安装,配置环境
    火炬之光2_辅助工具 内存读写相关
    学习资料
    如何在google colab加载kaggle数据
    Trie树
    日常
    Kmeans
    【leet-code】135. 加油站
    Mac CLion下OpenGL环境配置
  • 原文地址:https://www.cnblogs.com/gmh77/p/13991695.html
Copyright © 2011-2022 走看看