【JZOJ3129】数三角形

版权声明:欢迎dalao指出错误暴踩本SD,蒟蒻写的博客转载也要吱一声 https://blog.csdn.net/enjoy_pascal/article/details/89683406

description

在一只大灰狼偷偷潜入Farmer Don的牛群被群牛发现后,贝西现在不得不履行着她站岗的职责。从她的守卫塔向下瞭望简直就是一件烦透了的事情。她决定做一些开发智力的小练习,防止她睡着了。

想象牧场是一个X,Y平面的网格。她将N只奶牛标记为1…N (1 <= N <= 100,000),每只奶牛的坐标为X_i,Y_i (-100,000 <= X_i <= 100,000;-100,000 <= Y_i <= 100,000; 1 <= i <=N)。然后她脑海里想象着所有可能由奶牛构成的三角形。如果一个三角形完全包含了原点(0,0),那么她称这个三角形为“黄金三角形”。原点不会落在任何一对奶牛的连线上。另外,不会有奶牛在原点。

给出奶牛的坐标,计算出有多少个“黄金三角形”。


analysis

  • 符合的三角形数量可以是总的 C n 3 C^3_{n} 减掉不符合的三角形数量

  • 统计不符合的数量,有一种 O ( n ) O(n) 的方法

图是盗的

  • 对于每个点,它与原点的直线的同一侧所有点组成的三角形都不合法

  • 按极角排序一下,可以容易知道这样统计不重不漏

  • O ( n ) O(n) 枚举,剩下用一个指针扫描移就好了

  • 其实你可以看出来这就像旋转卡壳


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define MAXN 200005
#define ll long long
#define reg register ll
#define pi 3.1415926535897932384626
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))

using namespace std;

ll n,now=1,ans;

struct node
{
	ll x,y;
	double ang;
}f[MAXN];

O3 inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
O3 inline bool cmp(node a,node b)
{
	return a.ang<b.ang;
}
O3 inline ll judge(node a,node b)
{
	return a.x*b.y-b.x*a.y;
}
O3 int main()
{
	//freopen("T2.in","r",stdin);
	n=read(),ans=(n-2)*(n-1)*n/6;
	fo(i,1,n)f[i].x=read(),f[i].y=read(),f[i].ang=atan2(f[i].y,f[i].x)*180/pi;
	sort(f+1,f+n+1,cmp);
	fo(i,1,n)f[n+i]=f[i];
	fo(i,1,n)
	{
		while (now<n+i && judge(f[i],f[now])>=0)++now;
		ll temp=now-i-1;
		ans-=(temp-1)*temp/2;
	}
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/enjoy_pascal/article/details/89683406