http://acm.fzu.edu.cn/problem.php?pid=2242
题意:一个圆上有若干点(不重复),问你可以构成多少锐角三角形。。
思路:排序,枚举每一个点之后二分找到这个点的圆心延长线,之后统计钝角和直角三角形的个数(每次统计向量的左半部分,这样保证不会重复计数)。
排序方法,对于x根据所在象限增加偏移量,可以考虑以x轴划分,上半部分增加一倍偏移量并且-x。。下半部分两倍+x 。注意数组要延长一倍以便于枚举到3,4象限的时候得到正确答案。
坑点:fzoj是I64 。。。黑人问号了好长时间。。
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#define bug(x) cout<<" x "<<x<<endl;
using namespace std;
const long long maxn=1e5;
long long n,r;
long long a[50000];
long long x[50000];
char tmp[5];
int main(){
while(scanf("%I64d%I64d",&n,&r)!=EOF){
for(int i=1;i<=n;i++){
scanf("%I64d %s",&x[i],tmp);
if(x[i]==r) a[i]=maxn-x[i];
else if(x[i]==-r) a[i]=2*maxn+x[i];
else if(tmp[1]=='>')a[i]=maxn-x[i];
else if(tmp[1]=='<')a[i]=2*maxn+x[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++) a[n+i]=a[i]+2*maxn;
long long sum=n*(n-1)*(n-2)/6;
for(int i=1;i<=n;i++){
long long r=(long long)(upper_bound(a+i,a+n+i+1,a[i]+maxn)-a-1)-i;
sum-=r*(r-1)/2;
}
printf("%I64d
",sum);
}
return 0;
}