2019 牛客多校第八场 F

求平面上四个点形成三点包围一点的方案数。

极角排序扫过去,共线的情况要分类讨论。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef long long db;
  5. typedef db ll;
  6.  
  7. int sgn(db x){
  8. 	if (x<0) return -1;
  9. 	return x>0;
  10. }
  11.  
  12. #define Vec const vec &
  13. #define Point const point &
  14. struct vec{
  15. 	db x,y;
  16. 	vec():x(0),y(0){}
  17. 	vec(db x, db y):x(x),y(y){} //[i] init-list is easier to use in c++1x
  18. 	vec(db theta):x(cos(theta)),y(sin(theta)){}
  19.  
  20. 	db ang() const{return atan2(y,x);}
  21.  
  22. 	vec operator+(Vec v) const{return vec(x+v.x,y+v.y);}
  23. 	vec operator-(Vec v) const{return vec(x-v.x,y-v.y);}
  24. 	vec operator*(db a) const{return vec(x*a,y*a);}
  25. 	vec operator/(db a) const{return vec(x/a,y/a);}
  26.  
  27. 	db operator|(Vec v) const{return x*v.x+y*v.y;} //dot
  28. 	db operator&(Vec v) const{return x*v.y-y*v.x;} //cross
  29.  
  30. 	bool operator<(Vec v) const{return x==v.x?y<v.y:x<v.x;}
  31. 	int getid()const{
  32. 		if (x>=0) return y>0?1:4;
  33. 		return y>0?2:3;
  34. 	}
  35. 	void rd(){scanf("%lld%lld",&x,&y);}
  36. 	void prt(){printf("%lld %lld\n",x,y);}
  37. 	friend ostream& operator<<(ostream &o, Vec v){return o<<v.x<<','<<v.y;}
  38. };
  39. typedef vec point;
  40.  
  41. //cmp2 sort by angle without atan2
  42. // angle range [-pi,pi)
  43. bool cmp2(Vec a, Vec b){
  44. 	int d1=a.getid(),d2=b.getid();
  45. 	if (d1^d2) return d1<d2;
  46. 	return (a&b)>0;
  47. }
  48. const int N=1010;
  49. point v1[N],p[N];
  50. bool vis[N];
  51.  
  52. int main(){
  53. 	int n0; cin>>n0;
  54. 	for (int i=0;i<n0;i++) p[i].rd();
  55. 	ll ans=0;
  56. 	for (int i=0;i<n0;i++){
  57. 		ll n=0;
  58. 		ll sum=0;
  59. 		for (int j=0;j<n0;j++) if (i^j) v1[n++]=p[j]-p[i];
  60. 		sort(v1,v1+n,cmp2);
  61. 		ll l=0,r=1;
  62. 		v1[n]=v1[0];
  63. 		ll sum2=0;
  64. 		memset(vis,0,sizeof vis);
  65. 		for (;l<n;l++){
  66. 			ll sl,sr;
  67. 			vis[l]=1;
  68. 			for (sl=l;sl+1<n && (v1[sl+1]&v1[sl])==0 && (v1[sl+1]|v1[sl])>0;sl++) vis[sl]=1;
  69. 			for (;r<=sl || (!vis[r%n] && ((v1[l]&v1[r%n])>0 || (v1[l]&v1[r%n])==0 && (v1[l]|v1[r%n])>0));r++);
  70. 			ll cnt=r-l;
  71. 			if ((v1[l]&v1[r%n])==0 && (v1[l]|v1[r%n])<0){
  72. 				for (sr=r;(v1[(sr+1)%n]&v1[sr%n])==0 && !vis[(sr+1)%n] && (v1[(sr+1)%n]|v1[sr%n]);sr++);
  73. 				sum+=(sl-l+1)*(sl-l)*(sr-r+1)/2;
  74. 				sum+=(sl-l+1)*(sr-r+1)*(r-sl-1);
  75. 			}
  76. 			if (r-sl>1)	sum+=(sl-l+1)*(r-sl-1)*(r-sl-2)/2;
  77. 			sum+=(sl-l+1)*(sl-l)*(r-sl-1)/2;
  78. 			sum+=(sl-l+1)*(sl-l)*(sl-l-1)/6;
  79. 			for (int j=l;j<=sl;j++) vis[j]=0;
  80. 			l=sl;
  81. 		}
  82. 		ans+=n*(n-1)*(n-2)/6-sum+sum2/2;
  83. 	}
  84. 	cout<<ans<<'\n';
  85. 	return 0;
  86. }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注