• 【BZOJ】1914: [Usaco2010 OPen]Triangle Counting 数三角形


    【题意】给定坐标系上n个点,求能构成的包含原点的三角形个数,n<=10^5。

    【算法】极角排序

    【题解】补集思想,三角形个数为C(n,3)-不含原点三角形。

    将所有点极角排序。

    对于一个点和原点构成的直线,如果选择这个点和直线一侧的两个点就可以构成不含原点的三角形。

    每个点只统计半圈,这样扫1~n下来每个点就会被统计若干次和统计若干次,加起来刚好是答案。这也是基环树DP中的惯用套路。

    这样只要用双指针找到半圈内有多少点即可,比较一个点是否在直线一侧可以比较直线向量和目标点向量的叉积是否>0。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    using namespace std;
    const int maxn=100010,eps=1e-8;
    int n;
    long long ans;
    struct point{
        ll x,y;double angle;
        ll operator *(const point a)const{
            return x*a.y-a.x*y;//
        }
    }a[maxn];
    bool cmp(point a,point b){return fabs(a.angle-b.angle)<eps?a.x<b.x:a.angle<b.angle;}
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%lld%lld",&a[i].x,&a[i].y);
            a[i].angle=atan2(a[i].y,a[i].x);
        }
        sort(a,a+n,cmp);
        int r=1,num=0;ans=0;
        for(int i=0;i<n;i++){
            while(r!=i&&a[i]*a[r]>=0)r=(r+1)%n,num++;
            ans+=1ll*num*(num-1)/2;
            num--;
        }
        printf("%lld",1ll*n*(n-1)*(n-2)/6-ans);
        return 0;
    }
    View Code

    注意叉积计算后作为int,不是double。

  • 相关阅读:
    四叉树编码存储的实现
    窗体之间传递值的几种方法
    常见的六种排序算法实现
    OracleHelper类
    c#动态加载dll文件
    STL学习系列九:Map和multimap容器
    STL学习系列八:Set和multiset容器
    STL学习系列七:优先级队列priority_queue容器
    STL学习系列六:List容器
    STL学习系列五:Queue容器
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7703546.html
Copyright © 2020-2023  润新知