码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-10-21 16:29:31      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:fabs   col   max   play   int   多少   img   define   统计   

【题意】给定坐标系上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。

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

标签:fabs   col   max   play   int   多少   img   define   统计   

原文地址:http://www.cnblogs.com/onioncyc/p/7703546.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!