锐角三角形 (极角排序)

思路就不讲了,主要是想记录一下这个计模板

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define sz(x) x.size()
#define lbt(x) (x)&(-x)
#define rep(i,n) for(int i=0;i<n;i++)

using namespace std;

typedef pair<int, int> PII;
const int N = 2e6 + 10, EPS = 1e-9;

typedef double db;

inline int sign(db a) { return a<-EPS ? -1 : a>EPS; }

inline int cmp(db a, db b) { return sign(a - b); }


struct P {
    db x, y;
    P() {}
    P(db _x, db _y):x(_x), y(_y) {}
    P operator +(P p) { return { x + p.x,y + p.y }; }
    P operator -(P p) { return { x - p.x,y - p.y }; }
    P operator *(db d) { return { x * d,y * d }; }
    P operator /(db d) { return { x / d,y / d }; }

    bool operator<(P p)const {
        int c = cmp(x, p.x);
        if (c)return c == -1;
        return cmp(y, p.y) == -1;
    }

    bool operator == (P o)const {
        return cmp(x, o.x) == 0 && cmp(y, o.y) == 0;
    }

    db dot(P p) { return x * p.x + y * p.y; }//点积
    db det(P p) { return x * p.y - y * p.x; }//叉积

    db distTo(P p) { return (*this - p).abs(); }
    db alpha() { return atan2(y, x); }
    void read() { cin >> x >> y; }
    void write() { cout << "(" << x << "," << y << ")" << endl; }
    db abs() { return sqrt(abs2()); }
    db abs2() { return x * x + y * y; }
    P rot90() { return P(-y, x); }
    P unit() { return *this / abs(); }
    int quad()const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
    P rot(db an) { return  { x * cos(an) - y * sin(an) , x * sin(an) + y * cos(an) }; }
};

#define cross(p1, p2, p3) ((p2.x - p1.x)* (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))


void solve() {
    int n;cin >> n;
    vector<P>p(n);
    for (auto& t : p)t.read();
    int res = n * (n - 1) * (n - 2) / 6;
    for (int i = 0;i < n;i++) {
        vector<P>q;
        for (int j = 0;j < n;j++)if (j != i) {
            q.push_back(p[j] - p[i]);
        }
        sort(q.begin(), q.end(), [&](P a, P b) {
            int qa = a.quad(), qb = b.quad();
            if (qa != qb)return qa < qb;
            return sign(a.det(b)) > 0;
            });
        int t = q.size();
        for (int j = 0;j < t;j++)q.push_back(q[j]);
        int l = -1, r = -1;
        for (int j = 0;j < t;j++) {
            l = max(l, j + 1);
            r = max(r, j + 1);
            auto check1 = [&](P a, P b, int idl) {
                if (a.dot(b) > 0) {
                    if (a.det(b) != 0)return a.det(b) > 0;
                    return idl < t;
                }
                return false;
            };
            while (l < j + t && check1(q[j], q[l], l))l++;
            auto check2 = [&](P a, P b, int idr) {
                auto d = a.det(b);
                if (d != 0)return d > 0;
                return idr < t;
            };
            while (r < j + t && check2(q[j], q[r], r))r++;
            res -= r - l;
        }
    }
    cout << res << endl;
}

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    cout.tie(0);
    int _ = 1;
    cin >> _;
    while (_--)
        solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值