• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
镂空的行尸
   首页       联系   管理    订阅  订阅

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\n",ans - line/2);
    }
    return 0;
}

 

more crazy more get!
posted @ 2018-11-02 00:51  镂空的行尸  阅读(217)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3