zoukankan      html  css  js  c++  java
  • 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!
  • 相关阅读:
    一串东西跟着鼠标走
    仿select下拉框
    MD5,DES,RSA
    网站访问量统计
    linux 下 apache启动、停止、重启命令
    Blender绘制大脑表层,并高亮染色
    树莓派搭建LAMP,然后更改根目录
    树莓派使用Samba共享文件夹
    树莓派挂载移动硬盘
    [原创]一种基于Python爬虫和Lucene检索的垂直搜索引擎的实现方法介绍
  • 原文地址:https://www.cnblogs.com/wethura/p/9893595.html
Copyright © 2011-2022 走看看