• 2015 北京网络赛 C Protecting Homeless Cats hihoCoder 1229 树状数组


     题意:求在平面上 任意两点连线,原点到这个点的距离小于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
    ",ans);
        }
        return 0;
    }
    /*
    4 10
    0 2
    2 0
    0 100
    100 0
    */
    View Code
     
  • 相关阅读:
    龙芯地址空间详解
    JS匿名函数 Amy
    JS正则表达式 Amy
    JS对象 Amy
    Java 位图法排序
    Java Final
    JAVA 数组
    Java shuffle 算法
    jQuery object and DOM element
    Javascript 声明时用“var”跟不用"var"的区别
  • 原文地址:https://www.cnblogs.com/Opaser/p/4938430.html
Copyright © 2020-2023  润新知