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
  • 相关阅读:
    loj#6433. 「PKUSC2018」最大前缀和(状压dp)
    PKUWC2019游记
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7598930.html
Copyright © 2011-2022 走看看