zoukankan      html  css  js  c++  java
  • BZOJ 1914: [Usaco2010 OPen]Triangle Counting 数三角形

    http://www.lydsy.com/JudgeOnline/problem.php?id=1914

    题意:给定平面上N(<=10^5)个整点,任意三点可以组成一个三角形,求把原点包含在内部的三角形个数。保证原点不在两点连线上。

    我们反过来考虑,用总的三角形个数减去非法的三角形个数。
    总的三角形个数是(N3)=N(N1)(N2)6
    然后考虑非法三角形的情况,原点在三角形外部。作原点和三个点的连线,我们会发现一定是形成一个锐角,所以答案只跟每个点的极角有关。
    于是把每个点按照极角序排序,用单调队列维护一个半平面上的点,每次加入一个点时,删除队尾与该点成顺时针的点,此时对答案的贡献就是(M2),M为队列中点的个数,最后加入这个点,具体实现见代码。
    一些细节:把点按x坐标正负分成左右两部分,排序的时候就可以用叉积,单调队列扫的时候也用叉积判断。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 100005;
    struct P{ll x, y;}A[MAXN], B[MAXN], q[MAXN<<2];
    ll operator*(P a, P b){return a.x*b.y-a.y*b.x;} //叉积
    int cmp(P a, P b){return a*b<0;}
    int na, nb, N;
    int main()
    {
        scanf("%d", &N);
        for(int i=0; i<N; ++i){
            P p; scanf("%lld%lld", &p.x, &p.y);
            if(p.x>0 || (p.x==0 && p.y>0)) A[na++]=p; //右半部分
            else B[nb++]=p; //左半部分
        }
        sort(A, A+na, cmp); sort(B, B+nb, cmp);
        int hd=0, tl=0;
        for(int i=0; i<nb; ++i) q[tl++]=B[i];
        ll ans = (ll)N*(N-1)*(N-2)/6;
        for(int i=0; i<na; ++i){
            while(hd<tl && A[i]*q[hd]<0) hd++;
            ans -= (ll)(tl-hd)*(tl-hd-1)/2;
            q[tl++]=A[i];
        }
        for(int i=0; i<nb; ++i){
            while(hd<tl && B[i]*q[hd]<0) hd++;
            ans -= (ll)(tl-hd)*(tl-hd-1)/2;
            q[tl++]=B[i];
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    数据可视化——Matplotlib模块入门
    小甲鱼第23,24课后练习
    小甲鱼第28课课后练习
    小甲鱼第27课课后练习
    小甲鱼第25课课后练习
    小甲鱼第21课课后练习
    Java:泛型(一)
    决心考研之后
    Java:null
    树:哈夫曼编码解码及压缩存储
  • 原文地址:https://www.cnblogs.com/will7101/p/6506683.html
Copyright © 2011-2022 走看看