题目描述
题目大意:平面上有N个点. 求出所有以这N个点为顶点的三角形的面积和。
题解
枚举每一个点,以它为原点建立平面直角坐标系,然后其他的点按照极角排序。
向量的叉积满足分配律,所以可以two pointer一下,每一次右指针移动到最后一个与左指针夹角小于180°的地方,然后每加入一个向量,计算一下这个向量与两个指针之间所有向量的叉积,利用分配律。
看了PoPoQQQ的题解才发现,其实不用这么麻烦,可以将第一、四象限和x、y轴正半轴上的点按照极角排序,然后维护一个前缀和
原来是用了愚蠢的方法死慢死慢
不过这题还卡精度,建议全程int/long long,最后先*10再手动除
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 6005
const double pi=acos(-1.0);
struct Vector
{
int x,y;
double ang;
Vector(int X=0,int Y=0)
{
x=X,y=Y;
ang=atan2((double)y,(double)x);
}
bool operator < (const Vector &a) const
{
return ang<a.ang;
}
};
typedef Vector Point;
int n,vx,vy,x[N],y[N];
long long ans;
Point q[N];
long long Abs(long long x){return (x>0)?x:-x;}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]);
for (int i=1;i<=n;++i)
{
int cnt=0;
for (int j=1;j<=n;++j)
if (i!=j) q[++cnt]=Point(x[j]-x[i],y[j]-y[i]);
sort(q+1,q+cnt+1);
for (int i=1;i<=cnt;++i) q[cnt+i]=q[i],q[cnt+i].ang+=2*pi;
int l=1,r=0;
while (l<=cnt)
{
if (l>r) r=l,vx=0,vy=0;
while (r<=cnt<<1&&q[r].ang<q[l].ang+pi)
{
ans+=Abs((long long)q[r].x*vy-(long long)q[r].y*vx);
if (r<=cnt) vx+=q[r].x,vy+=q[r].y;
++r;
}
vx-=q[l].x,vy-=q[l].y;
++l;
}
}
ans=ans*5/3;
printf("%lld.%lld\n",ans/10,ans%10);
}