您的位置:首页 > 其它

HDU 5784 How Many Triangles

2016-08-03 12:31 387 查看
求二维平面上的n个点可以组合成多少个不同锐角三角形,有一个点位置不同即不同。

数一数锐角的数量A和直角+钝角的数量B,那么答案就是(A-2B)/3。

使用极角排序+two pointers就可以做到O(n2log n)。

这边钝角指代范围在90度到180度之间的角(不包括90和180)。

蒟蒻:没把同向的边处理好,结构体里重载运算的地方没改成ll。

极角排序:先按象限划分好,然后判一下逆时针就好了。

对于本题数据,在判是否同向时,先看是否同象限会略快。

极角排序+尺取

#include<set>
#include<ctime>
#include<queue>
#include<cstdio>
#include<bitset>
#include<cctype>
#include<bitset>
#include<cstdlib>
#include<cassert>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf (1<<30)
#define INF (1ll<<62)
#define fi first
#define se second
#define rep(x,s,t) for(register int x=s,t_=t;x<t_;++x)
#define per(x,s,t) for(register int x=t-1,s_=s;x>=s_;--x)
#define prt(x) cout<<#x<<":"<<x<<" "
#define prtn(x) cout<<#x<<":"<<x<<endl
#define pb(x) push_back(x)
#define hash asfmaljkg
#define rank asfjhgskjf
#define y1 asggnja
#define y2 slfvm
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
template<class T>void sc(T &x){
int f=1;char c;x=0;
while(c=getchar(),c<48)if(c=='-')f=-1;
do x=x*10+(c^48);
while(c=getchar(),c>47);
x*=f;
}
template<class T>void nt(T x){
if(!x)return;
nt(x/10);
putchar(x%10+'0');
}
template<class T>void pt(T x){
if(x<0)putchar('-'),x=-x;
if(!x)putchar('0');
else nt(x);
}
template<class T>void ptn(T x){
pt(x);putchar('\n');
}
template<class T>void pts(T x){
pt(x);putchar(' ');
}
template<class T>inline void Max(T &x,T y){if(x<y)x=y;}
template<class T>inline void Min(T &x,T y){if(x>y)x=y;}

const int maxn=2005;
int n;
int x[maxn],y[maxn];
struct abcd{
ll x,y;int v;
abcd(){}
abcd(ll x_,ll y_){
//x==0&&y==0?
x=x_;y=y_;
if(x>0&&y>=0)v=0;
else if(x<=0&&y>0)v=1;
else if(x<0&&y<=0)v=2;
else if(x>=0&&y<0)v=3;
}
inline ll operator*(const abcd &a)const{
return x*a.x+y*a.y;
}
inline ll operator^(const abcd &a)const{
return x*a.y-a.x*y;
}
inline abcd operator+(const abcd &a)const{
return abcd(x+a.x,y+a.y);
}
inline abcd operator-(const abcd &a)const{
return abcd(x-a.x,y-a.y);
}
inline bool operator<(const abcd &a)const{
if(v^a.v)return v<a.v;
return x*a.y-a.x*y>0;
}
inline bool operator==(const abcd &a)const{
return v==a.v&&x*a.y==a.x*y;
}
}d[maxn<<1];
void solve(){
rep(i,0,n)sc(x[i]),sc(y[i]);
ll A=0,B=0;
rep(i,0,n){
int tot=0;
rep(j,0,n)if(i!=j)
d[tot++]=abcd(x[j]-x[i],y[j]-y[i]);
sort(d,d+tot);

rep(j,tot,tot<<1)d[j]=d[j-tot];
int top=1,cnt=0;
rep(j,0,tot){
Max(top,j+1);
while(top<j+tot){
if((d[j]^d[top])>0)
top++;
else if(d[j]==d[top]){
cnt++;
top++;
}
else break;
}
B+=top-j-1-cnt;
if(cnt)cnt--;
}//0<d<180°
top=1,cnt=0;
rep(j,0,tot){
Max(top,j+1);
while(top<j+tot){
if((d[j]^d[top])>0&&d[top]*d[j]>0)
top++;
else if(d[j]==d[top]){
cnt++;top++;
continue;
}
else break;
}
A+=top-j-1-cnt;
if(cnt)cnt--;
}//0<d<90°
}
ll ans=(A-(B-A)*2)/3;
ptn(ans);
}

int main(){
//  freopen("pro.in","r",stdin);
//  freopen("chk.out","w",stdout);
while(~scanf("%d",&n))solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: