Hướng dẫn giải của Diện Tích Bao Lồi


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

template <class T> int sgn(T x) { return (x > 0) - (x < 0); }
template<class T>
struct Point {
    typedef Point P;
    T x, y;
    explicit Point(T x=0, T y=0) : x(x), y(y) {}
    bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); }
    bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); }
    P operator+(P p) const { return P(x+p.x, y+p.y); }
    P operator-(P p) const { return P(x-p.x, y-p.y); }
    P operator*(T d) const { return P(x*d, y*d); }
    P operator/(T d) const { return P(x/d, y/d); }
    T dot(P p) const { return x*p.x + y*p.y; }
    T cross(P p) const { return x*p.y - y*p.x; }
    T cross(P a, P b) const { return (a-*this).cross(b-*this); }
    T dist2() const { return x*x + y*y; }
    double dist() const { return sqrt((double)dist2()); }
    // angle to x-axis in interval [-pi, pi]
    double angle() const { return atan2(y, x); }
    P unit() const { return *this/dist(); } // makes dist()=1
    P perp() const { return P(-y, x); } // rotates +90 degrees
    P normal() const { return perp().unit(); }
    // returns point rotated 'a' radians ccw around the origin
    P rotate(double a) const {
        return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); }
    friend ostream& operator<<(ostream& os, P p) {
        return os << "(" << p.x << "," << p.y << ")"; }
    friend istream& operator>>(istream& is, P& p) {
        return is >> p.x >> p.y;
    }
};

typedef Point<ll> P;
vector<P> convexHull(vector<P> pts) {
    if (sz(pts) <= 1) return pts;
    sort(all(pts));
    vector<P> h(sz(pts)+1);
    int s = 0, t = 0;
    for (int it = 2; it--; s = --t, reverse(all(pts)))
        for (P p : pts) {
            while (t >= s + 2 && h[t-2].cross(h[t-1], p) <= 0) t--;
            h[t++] = p;
        }
    return {h.begin(), h.begin() + t - (t == 2 && h[0] == h[1])};
}

template<class T>
T polygonArea2(vector<Point<T>>& v) {
    T a = v.back().cross(v[0]);
    rep(i,0,sz(v)-1) a += v[i].cross(v[i+1]);
    return a;
}

ll ccw(P a, P b, P c) {
    return (b - a).cross(c - a);
}

bool half(P p) {
    return p.y > 0 || (p.y == 0 && p.x >= 0);
}

bool cmpPolar(const P &a, const P &b) {
    return make_tuple(half(a), 0, a.dist2()) < make_tuple(half(b), a.cross(b), b.dist2());
}

// check if point p is between a and b
bool between(const P &a, const P &b, const P &p) {
    ll da = (b - a).dot(a);
    ll db = (b - a).dot(b);
    ll dp = (b - a).dot(p);
    if (da > db) swap(da, db);
    return (da <= dp && dp <= db);
}

const int MOD = (int)1e9 + 7;

void solve() {
    int n; scanf("%d", &n);
    vector<P> pt(n);
    for(int i = 0; i < n; ++i) {
        cin >> pt[i];
    }

    vector<ll> e2(n+1);
    e2[0] = 1;
    for(int i = 1; i <= n; ++i) {
        e2[i] = (e2[i-1] * 2) % MOD;
    }

    ll ans = 0;
    for(int i = 0; i < n; ++i) {
        P origin = pt[i];
        P zero = P{0, 0};

        vector<P> d;
        for(int j = 0; j < n; ++j) {
            if (i != j) d.push_back(pt[j] - origin);
        }

        sort(all(d), cmpPolar);

        int k = d.size();
        int r = 0;
        for(int l = 0; l < k; ++l) {            
            if (l == r) ++r;
            while (r - l < k) {
                ll dir = d[l].cross(d[r%k]);
                if (!(dir > 0 || (dir == 0 && !between(zero, d[l], d[r%k])))) break;
                ++r;
            }
            // printf("l, r: %d %d\n", l, r);
            int cnt = r - l - 1;

            ll val = origin.cross(d[l] + origin) % MOD;
            ll contribute = e2[cnt] % MOD;

            // cout << origin << " " << d[l] + origin << endl;
            // printf("val, cnt: %lld %d\n", val, cnt);

            ans = (ans + val * contribute) % MOD;
            ans = (ans + MOD) % MOD;
        }
    }

    cout << ans << endl;
}

int main() {
    int t; scanf("%d", &t);
    while (t--) solve();

    return 0;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.