• How Many Triangles (极角排序 + 尺取法)


      题意:二维平面与有很多个点,然后求构成锐角三角形的个数。

      思路:对于每一个三角形我们知道存在至少2个锐角,只要有一个钝角就不行了,所以我们的想法就是枚举所有夹角的状态,然后得知情况,确定用总个数减去-成线或者成钝角的数量/2(除以2是因为计算过程中重复了)。那么应该如何枚举?我们枚举夹角的顶点然后就出其他点的极角,排序,然后尺取法左端点表示与当前点为锐角的个数,右端点表示锐角+钝角,过程中相减可以得到锐角数量。

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int maxn = 2000 + 7;
    struct P{
        ll x, y;
        P() {}
        P(ll x, ll y): x(x), y(y) {}
        P operator + (P p) {
            return P(x + p.x, y + p.y);
        }
        void read() {
            scanf("%lld%lld", &x, &y);
        }
        P operator - (P p) {
            return P(x - p.x, y - p.y);
        }
        ll dot(P p) {//点积
            return x * p.x + y * p.y;
        }
        ll det(P p) {//叉积
            return x * p.y - y * p.x;
        }
        bool operator < (const P &p) const{
            if(y * p.y <= 0) {
                if(y > 0 || p.y > 0) return y < p.y;
                if(y == 0 && p.y == 0)return x < p.x;
            }
            return x * p.y - y * p.x > 0;
        }
    }p[maxn], q[maxn << 1];
    
    int main(){
        int n;while(~scanf("%d", &n)) {
            ll ans = 1ll * n * (n - 1) * (n - 2) / 6;
            ll line = 0;
            for(int i = 0; i < n; i ++) p[i].read();
            for(int i = 0; i < n; i ++) {
                int tot = 0;
                for(int j = 0; j < n; j ++)
                    if(i != j) q[tot ++] = p[j] - p[i];
                ll subtrat = 0;
                sort(q, q + tot);
                for(int j = 0; j < tot; j ++) q[j + tot] = q[j];
                for(int j = 1; j < tot; j ++) {
                    if(q[j - 1].det(q[j]) == 0 && q[j - 1].dot(q[j]) > 0) subtrat ++;
                    else subtrat = 0;
                    line += subtrat;
                }
                int l = 0, r = 0;
                for(int j = 0; j < tot; j ++) {
                    while(l <= j || (l < j + tot && q[l].det(q[j]) < 0 && q[j].dot(q[l]) > 0)) l ++;
                    while(r <= j || (r < j + tot && q[r].det(q[j]) < 0)) r ++;
                    ans -= r - l;
                }
            }
            printf("%lld
    ",ans - line/2);
        }
        return 0;
    }
    more crazy more get!
  • 相关阅读:
    ubuntu 15.04默认root用户登陆
    hive的not in
    Spark 1.4.1中Beeline使用的gc overhead limit exceeded
    Sequoiadb该如何选择合适的SQL引擎
    scala的object知识点
    scala中同步块
    英语口语练习系列-C36-城市-谈论活动-登高
    英语口语练习系列-C35-马戏-谈论语言-己亥杂诗
    英语口语练习系列-C34-儿童-谈论物品和人-武陵春
    英语口语练习系列-C33-露营-谈论日期-离思
  • 原文地址:https://www.cnblogs.com/wethura/p/9893595.html
Copyright © 2020-2023  润新知