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; }