bzoj1914

Posted 123456

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1914相关的知识,希望对你有一定的参考价值。

极角排序

先开始想了很多分割方法,发现都不对,最后觉得只能极角搞搞,就看了答案

我们发现,一个点的原点构成的直线把平面分成了两半,那么只由一边点和这个点构成的三角形肯定不包含原点,那么我们按极角排序,然后计算右边有多少点C(x,2)就行了。因为一个三角形有三个点,枚举到中间那个点的时候这个三角形不会被计算,而如果两边都计算的话就会算重两次,于是我们只计算在右边的三角形就不会重负和遗漏了

极角排序就是计算atan2(y,x),计算出和x轴的弧度夹角,按这个排序就行了

技术分享
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
const double pi = acos(-1);
struct points {
    double x, y, angle;
    points(double x = 0, double y = 0, double angle = 0) : x(x), y(y), angle(angle) {}
    bool friend operator < (points A, points B)
    {
        return A.angle < B.angle;
    }
} a[N];
int n, cnt, pos;
long long ans;
inline long long Sum(long long x)
{
    return x * (x - 1ll) * (x - 2ll) / 6ll;
}
inline long long calc(long long x)
{
    return x * (x - 1ll) / 2ll;
}
inline double A(double x)
{
    return x > 0 ? x : 2 * pi + x;
}
int main()
{
    scanf("%d", &n);
    ans = Sum(n);
    for(int i = 1; i <= n; ++i)
    {
        double x, y, angle;
        scanf("%lf%lf", &x, &y);
        angle = atan2(y, x);
        if(angle < 0) angle += 2 * pi;
        a[i] = points(x, y, angle);
    }
    sort(a + 1, a + n + 1);
    for(int i = 2; i <= n; ++i) if(a[i].angle - a[1].angle > pi) 
    {
        pos = i;
        break;
    }
    cnt = pos - 1;
    for(int i = 1; i <= n; ++i)
    {
        --cnt;
        while(A(a[pos].angle - a[i].angle) < pi && pos != i) 
        {
            ++pos;
            pos = (pos - 1) % n + 1;
            ++cnt;
        }
        ans -= calc(cnt);
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

以上是关于bzoj1914的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1914: [Usaco2010 OPen]Triangle Counting 数三角形

bzoj 1914: [Usaco2010 OPen]Triangle Counting 数三角形——极角排序

如何在地图片段 API v2 布局顶部添加按钮

Bzoj2339--Hnoi2011卡农

为啥选项卡和片段不显示?

[bzoj1966][Ahoi2005][VIRUS 病毒检测] (字符串dp)