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

Description

给出一堆点,问有多少包含原点的三角形,\(n\leqslant 10^5\).

Sol

极角排序.

首先按极角大小排一下序,我先按象限排再计算一下叉积也相当于极角排序了...其实主要是我不太会用cmath里的atan什么的...

然后每次维护一个半平面,他和这些半平面中的点形成的三角形都不合法.

Code

/**************************************************************
    Problem: 1914
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:392 ms
    Memory:2868 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
#define debug(a) cout<<#a<<"="<<a<<" "
#define mpr make_pair
#define x first
#define y second
typedef long long LL;
typedef pair< LL,LL > pr;
const int N = 1e5+50;
 
int n;LL ans;
pr p[N];
 
inline int in(int x=0,char ch=getchar(),int v=1) {
    while(ch>'9' || ch<'0') v=(ch=='-'?-1:v),ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x*v;
}
double Len(const pr &a) { return sqrt(a.x*a.x+a.y*a.y); }
LL operator * (const pr &a,const pr &b) { return a.x*b.y-a.y*b.x; }
int cmp(const pr &a,const pr &b) {
//  return atan2(a.y,a.x) < atan2(b.y,b.x);
 
    if((b.y>=0) != (a.y>=0)) return a.y>b.y;
    double l1=Len(a),l2=Len(b);
    if(a.y<0) {
        return (a.x*l2 == b.x*l1)? (l1<l2) : a.x*l2<b.x*l1;
    } else {
        return (a.x*l2 == b.x*l1)? (l1<l2) : a.x*l2>b.x*l1;
    }
}
int main() {
    n=in();
    for(int i=0;i<n;i++) {
        int x=in(),y=in();
//      debug(x),debug(y)<<endl;
        p[i]=mpr(x,y);
    }
    sort(p,p+n,cmp);
     
//  for(int i=0;i<n;i++) cout<<p[i].x<<" "<<p[i].y<<endl;
    ans=(LL)n*(n-1)*(n-2)/6;
    for(int i=0,s=1,l=1;i<n;i++) {
        while(l!=i && (p[i]*p[l]>=0)) s++,l=(l+1)%n;
//      debug(l),debug(s)<<endl;
        ans-=(LL)(s-1)*(s-2)/2;
        s--;
    }
    printf("%lld\n",ans);
    return 0;
}

  

posted @ 2017-01-12 08:50  北北北北屿  阅读(205)  评论(0编辑  收藏  举报