CF1284E New Year and Castle Construction

题面:https://codeforces.com/problemset/problem/1284/E
题解:
考虑一个五元组形成凸包的情况。
由于三点不共线,因此只可能有三种情况:
1.凸包含有3个点:此时贡献为2;
2.凸包含有4个点:贡献为1;
3.凸包含有5个点:贡献为0。
设这三种情况的个数分别为(x_3),(x_4),(x_5),
那么答案即为2(x_3)+(x_4)
这个东西很不好求,考虑转化。
首先发现(x_3)+(x_4)+(x_5)=(C(n,5))
其次,发现如果能求出3(x_3)+4(x_4)+5(x_5),
那答案就很容易求出。这个式子的几何意义即为
(sum)每一条边所在的凸包数。
用双指针求出这个东西即可。
时间复杂度:O((n^2)logn)
代码:

#include<bits/stdc++.h>
using namespace std;
#define re register ll
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline ll
#define STS system("pause")
template<class D>I read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
typedef pair<ll,ll>pii;
struct Vec{
	ll x,y;
	Vec(ll _x=0,ll _y=0){x=_x;y=_y;}
	friend Vec operator + (Vec a,Vec b){return Vec(a.x+b.x,a.y+b.y);}
	friend Vec operator - (Vec a,Vec b){return Vec(a.x-b.x,a.y-b.y);}
	friend ll operator ^ (Vec a,Vec b){return a.x*b.y-a.y*b.x;}
	friend bool operator < (Vec a,Vec b){
		pii A=make_pair(a.x,a.y),B=make_pair(b.x,b.y);
		bool c=A<make_pair(0ll,0ll),d=B<make_pair(0ll,0ll);
		return c==d?(a^b)>=0:c<d;
	}
}p[2550];
vector<Vec>v;
ll n,m,ans,cnt;
IN C(ll x,ll y){
	re res=1;
	F(i,0,y-1){res*=(x-i);res/=(i+1);}
	return res;
}
int main(){
	read(n);
	F(i,1,n)read(p[i].x),read(p[i].y);
	F(i,1,n){
		v.clear();
		F(j,1,n){
			if(i==j)continue;
			v.emplace_back(p[j]-p[i]);
		}		
		sort(v.begin(),v.end());
		m=0;
		F(j,0,v.size()-1){
			while(m<j+v.size()&&(v[j]^v[m%v.size()])>=0)m++;
			cnt+=C(m-j-1,3);
		}
	}
	ans=C(n,5)*5ll-cnt;
	cout<<ans;
	return 0;
}
原文地址:https://www.cnblogs.com/Purple-wzy/p/12152663.html