1284E

计算几何

先枚举被围住的点 计算合法比较困难 考虑计算不合法方案数 

枚举其他点 选一个点连线作为基准边 当其他三个点连线都在基准边的一侧时不合法 极角排序+双指针统计即可

时间复杂度$O(n^{2}logn)$

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5005;
int n;
int x[maxn], y[maxn];
struct Vec {
    int x, y;
    Vec() = default;
    Vec(int _x, int _y) : x(_x), y(_y) {}
    ll friend operator ^ (const Vec &a, const Vec &b) {
        return 1LL * a.x * b.y - 1LL * a.y * b.x;
    }
    bool friend operator < (const Vec &a, const Vec &b) {
        if(1LL * a.y * b.y < 0) {
            return a.y > b.y;
        }
        return (a ^ b) > 0;
    }
} st[maxn];
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
         scanf("%d%d", &x[i], &y[i]);
    }
    ll ans = 0;
    for(int i = 1; i <= n; ++i) {
        int top = 0;
        for(int j = 1; j <= n; ++j) {
            if(j != i) {
                st[++top] = Vec(x[j] - x[i], y[j] - y[i]);
            }
        }
        sort(st + 1, st + top + 1);
        for(int j = 1; j < n; ++j) {
            st[++top] = st[j];
        }
        int pos = 1;
        for(int j = 1; j < n; ++j) {
            pos = max(pos, j);
            while(pos + 1 <= top && (st[j] ^ st[pos + 1]) > 0) {
                ++pos;
            }
            ll c = pos - j;
            ans += c * (c - 1) * (c - 2) / 6LL;
        }
    }
    printf("%lld\n", 1LL * n * (n - 1) * (n - 2) * (n - 3) * (n - 4) / 24LL - ans);
    return 0;
}
View Code

 

posted @ 2020-01-27 23:00  19992147  阅读(125)  评论(0编辑  收藏  举报