【Codeforces 1025F】Disjoint Triangles

计算几何。

题目大意:

给定 $n$ 个点,求能找到几对三角形,满足它们的顶点是 $n$ 个点中的若干个,且不相交。

题解:

两个三角形没有相交,则必然存在两条内公切线,并且两个三角形分别在公切线两端。

我们枚举这条公切线上的两个顶点,令它们分别为两个三角形的顶点。然后求出两边分别有多少个点,再计数即可。

具体计算时,先枚举一个点,然后以这个点为原点对其他点极角排序,然后按照极角序枚举每一条公切线即可。可以通过二分或者双指针的方式得到两边分别有多少个点。

时间复杂度 $O(n^2\log n)$。

Code:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
const double pi=acos(-1);
using namespace std;
const int N=2005;
struct point{
    int x,y;
    double T;
    inline bool operator<(const point&rhs)const{return T<rhs.T;}
}p[N],a[N];
int n;
long long ans=0;
inline long long calc(int x){return(x-1LL)*x/2;}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d%d",&p[i].x,&p[i].y);
    for(int i=1;i<=n;++i){
        memcpy(a,p,sizeof a);
        swap(a[i],a[1]);
        for(int i=2;i<=n;++i)a[i].T=atan2(a[i].y-a[1].y,a[i].x-a[1].x);
        sort(a+2,a+n+1);
        for(int i=2;i<=n;++i)if(a[i].T-1e-13>0){
            int l=i,r=lower_bound(a+2,a+n+1,(point){0,0,a[i].T-pi})-a;
            int L=l-r;
            ans+=1LL*calc(L)*calc(n-2-L);
        }
    }
    printf("%lld\n",ans);
    return 0;
}