题意:求在平面上 任意两点连线,原点到这个点的距离小于d的点对有多少个,n=200000;
解: 以原点为圆心做一个半径为d的圆,我们知道圆内的点和园内以外的点的连线都是小于d的还有,圆内和园内的点联线也是小于d的,那么需要处理的是圆外和圆外的点。
以每个圆外的点 向圆做切线 然后我们知道有绿色点区域是允许和他搭配的
那么这些点有一个共同特点 那就他们和圆的切线都在 那个点切点的一侧,这样我们就让每个点 转化为两个切点,然后按照极角排序,求出那些不想交区间就是不合法的
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> using namespace std; typedef long long LL; const int maxn=200005*2; const double eps=0.000000000001; const double PI=acos(-1.0); struct Point { double x,y; Point(double cx=0,double cy=0) { x=cx; y=cy; } }; struct Circle{ Point c; double r; Circle(Point c,double r):c(c),r(r){} Point point(double a) { return Point(c.x+cos(a)*r,c.y+sin(a)*r); } }; int dcmp(double a) { if(fabs(a)<eps)return 0; return a<0?-1:1; } double angle(Point v) { return atan2(v.y,v.x); } Point operator -(Point A, Point B) { return Point(A.x-B.x,A.y-B.y); } double Length(Point c) { return sqrt(c.x*c.x+c.y*c.y); } Point Rotate(Point A, double rad) { return Point(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); } void getTangents(Point p, Circle C,double &A, double &B) { Point u=p; double dist=Length(u); if(dcmp(dist-C.r)==0){ double a=atan2(p.y,p.x); if(a<0){ B=A=a+PI*2; }else A=B=a; }else{ double ang=acos(C.r/dist); Point t=Rotate(u,ang); double a=atan2(t.y,t.x); if(a<0) { A=a+PI*2; B=a-ang*2+PI*2; }else{ A=a; B=a-ang*2; if(B<0)B+=PI*2; } } } Point P[maxn]; struct Elem { double L,R; int cL,cR; bool operator <(const Elem &rhs)const { return cL<rhs.cL||(cL==rhs.cL&&cR<rhs.cR); } }E[maxn]; double JJ[maxn*2]; int C[maxn*2]; int lowbit(int x) { return x&(-x); } void add(int x,int v,int n) { if(x<=0)return ; while(x<=n) { C[x]+=v; x+=lowbit(x); } } int sum(int x) { int ans=0; while(x>0) { ans+=C[x]; x-=lowbit(x); } return ans; } int main() { int n; double d; while(scanf("%d%lf",&n,&d)==2) { LL ge=0,nu=0,cc=0; Circle c(Point(0,0),d); for(int j=0; j<n; j++) { scanf("%lf%lf",&P[nu].x,&P[nu].y); if(dcmp(Length(P[nu])-d)<0) { ge++; } else { getTangents(P[nu],c,E[nu].L,E[nu].R); if(E[nu].L>E[nu].R)swap(E[nu].L,E[nu].R); JJ[cc++]=E[nu].L;JJ[cc++]=E[nu].R; nu++; } } sort(JJ,JJ+cc); ge=1; for(int i=1; i<cc; i++) { if(dcmp(JJ[i]-JJ[ge-1])>0)JJ[ge++]=JJ[i]; } cc=ge; for(int i=0; i<=cc; i++)C[i]=0; for(int i=0; i<nu; i++) { E[i].cL=upper_bound(JJ,JJ+cc,E[i].L)-JJ; E[i].cR=upper_bound(JJ,JJ+cc,E[i].R)-JJ; add(E[i].cL,1,cc); add(E[i].cR,-1,cc); } sort(E,E+nu); LL buhefa=0; for(int i=0; i<nu; i++) { LL d1= sum(E[i].cR); LL d2= sum(E[i].cL-1); buhefa+=d1-d2; add(E[i].cL,-1,cc); add(E[i].cR,1,cc); } LL nn=n; LL ans=nn*(nn-1)/2-buhefa; printf("%lld\n",ans); } return 0; } /* 4 10 0 2 2 0 0 100 100 0 */
时间: 2024-11-13 06:55:46