bzoj1914 Triangle Counting 数三角形【极角排序】

来源:互联网 发布:excel矩阵相乘 编辑:程序博客网 时间:2024/05/24 03:31

解题思路:

可以发现,对于一个不是黄金三角形的三角形,有且仅有两个顶点满足:另外两个顶点在其与原点连线同侧。所以我们可以用所有三角形个数(C3n)减去不满足的个数得到答案。

将所有点极角排序,枚举每个点,为了去重对于一个顶点只算在其与原点连线右侧的点数,那么不合法的三角形数就是C2n,又注意到随着点的枚举,不合法的点也是随之单调旋转的,所以用两个指针即可。

PS:
原来极角排序可以用atan2(y,x)函数;
它可以算出向量(x,y)与x正半轴的弧度,值域为[-ππ]。
感觉计算几何白学了……我以前自己写细节调到吐血……

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<ctime>#include<vector>#include<set>#define ll long longusing namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());    if(c=='-')f=-1,c=getchar();    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int N=100000;struct point{    int x,y;    double k;    inline friend bool operator < (const point &a,const point &b)    {return a.k<b.k;}    inline friend ll operator * (const point &a,const point &b)    {return 1ll*a.x*b.y-1ll*a.y*b.x;}}p[N];int n;ll ans;int main(){    //freopen("lx.in","r",stdin);    n=getint();ans=1ll*n*(n-1)*(n-2)/6;    for(int i=0;i<n;i++)        p[i].x=getint(),p[i].y=getint(),p[i].k=atan2(p[i].y,p[i].x);    sort(p,p+n);    for(int i=0,cnt=0,j=0;i<n;i++)    {        if(cnt)cnt--;        while(p[i]*p[(j+1)%n]>0)            cnt++,j=(j+1)%n;        ans-=1ll*cnt*(cnt-1)/2;    }    cout<<ans<<'\n';    return 0;}
阅读全文
0 0
原创粉丝点击