FZOJ 2242

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;
}


原文地址:https://www.cnblogs.com/zhangxianlong/p/10672524.html