zoukankan      html  css  js  c++  java
  • bzoj 1914: [Usaco2010 OPen]Triangle Counting 数三角形——极角排序

    Description

    在一只大灰狼偷偷潜入Farmer Don的牛群被群牛发现后,贝西现在不得不履行着她站岗的职责。从她的守卫塔向下瞭望简直就是一件烦透了的事情。她决定做一些开发智力的小练习,防止她睡着了。想象牧场是一个X,Y平面的网格。她将N只奶牛标记为1…N (1 <= N <= 100,000),每只奶牛的坐标为X_i,Y_i (-100,000 <= X_i <= 100,000;-100,000 <= Y_i <= 100,000; 1 <= i <=N)。然后她脑海里想象着所有可能由奶牛构成的三角形。如果一个三角形完全包含了原点(0,0),那么她称这个三角形为“黄金三角形”。原点不会落在任何一对奶牛的连线上。另外,不会有奶牛在原点。给出奶牛的坐标,计算出有多少个“黄金三角形”。顺便解释一下样例,考虑五只牛,坐标分别为(-5,0), (0,2), (11,2), (-11,-6), (11,-5)。下图是由贝西视角所绘出的图示。 

    Input

    第一行:一个整数: N 第2到第N+1行: 每行两个整数X_i,Y_i,表示每只牛的坐标

    Output

    * 第一行: 一行包括一个整数,表示“黄金三角形的数量”

    Sample Input

    5
    -5 0
    0 2
    11 2
    -11 -6
    11 -5

    Sample Output

    5
    ————————————————————————————————
    这道题我们发现直接求黄金三角形就很难求 那么正难取反 我们可以用总的减去不符合的
    那么我们考虑某一个点 那么我们从原点向这个点连一条直线 
    这样之后我们从这条线的左边或者右边选点 选出来的点一定是不包含原点的
    我们单独考虑一个三角形(不包含原点类的)从原点向三个端点连线
    观察发现 有一条是经过这个三角形 一条三角形在这条线的顺时针方向 一条三角形在这条线的逆时针方向
    所以我们单独考虑一个方向就不会算重了 第一次接触极角排序 我们按顺时针的方向排序 从第一象限开始跑
    求一下顺时针方向180有多少个点 有一个结论 当前点 x1 x2 和他顺时针180的一个点 x2 y2 
    那么 y2*x1<y1*x2 这个可以利用差积证明 或者直接分类证明咯 然后就可以写辣233
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    using std::sort;
    const int M=2e5+7,inf=0x3f3f3f3f;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n;
    struct pos{int x,y,wh; double k;}q[M];
    bool cmp(pos a,pos b){return a.wh!=b.wh?a.wh<b.wh:a.k>b.k;}
    int main(){
        int x,y;
        n=read();
        for(int i=1;i<=n;i++){
            x=read(); y=read();
            q[i].x=x; q[i].y=y;
            if(x) q[i].k=1.0*y/x; else q[i].k=-inf;
            if(x>0&&y>=0) q[i].wh=1;
            else if(x>=0&&y<0) q[i].wh=2;
            else if(x<0&&y<=0) q[i].wh=3;
            else q[i].wh=4;
        }
        LL ans=1LL*n*(n-1)*(n-2)/6;
        sort(q+1,q+1+n,cmp);
        LL sum=1,ly=2;
        for(int i=1;i<=n;i++){
            sum--;
            while(1LL*q[ly].y*q[i].x<1LL*q[i].y*q[ly].x){
                ly++; sum++;
                if(ly>n) ly-=n;
            }
            ans=ans-sum*(sum-1)/2;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    韦德螺旋: 这真是一个螺旋吗?
    山上你能看到什么动物?
    你能够30秒内一字不差的念完它吗? 注意, 是读“颜色”, 不是让你识字.
    路透斯沃德的不可能的三角形
    换个角度, 青蛙也许就是白马王子
    这是一张很有趣的图片, 通常女性会先看到月亮, 男性会先看到人脸. 如果相反, 表示你体内的异性荷尔蒙偏高哦!
    亲吻的情侣幻觉: 这幅虚幻的亲吻由美国艺术家杰里•唐恩创作.
    PostgreSQL的 initdb 源代码分析之七
    PostgreSQL的initdb 源代码分析之六
    PostgreSQL的initdb 源代码分析之五
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7598930.html
Copyright © 2011-2022 走看看