Editorial for Diện Tích Bao Lồi


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
#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;
}

Comments

Please read the guidelines before commenting.


There are no comments at the moment.