Loading

BZOJ 2564

这道题挺像的,就不再多讲了。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;

struct Point {
    ll x, y;
    Point(){x=y=0;}
    Point(ll _x, ll _y):x(_x),y(_y){}
    Point operator-(const Point& _p) const{return Point(x-_p.x, y-_p.y);}
    Point operator+(const Point& _p) const{return Point(x+_p.x, y+_p.y);}

    ll operator*(const Point& _p) const{return x * _p.x + y * _p.y;}
    ll operator^(const Point& _p) const{return x*_p.y - y*_p.x;}

    void input(){scanf("%lld%lld", &x, &y);}
    /*sort*/
    bool operator==(const Point& _p) const{return x==_p.x&&y==_p.y;}
    bool operator<(const Point& _p) const{return x==_p.x ? y<_p.y : x<_p.x;}

} A[N], B[N], C[N];

ll cro(Point a, Point b, Point c) {return (b-a) ^ (c-a);}
ll dot(Point a, Point b, Point c) {return (b-a) * (c-a);}

int ConvexHull(Point *p, int n, Point* ch, int flag=1) {
    sort(p, p+n);      //先比较x坐标,再比较y坐标
    if (flag) n = unique(p, p+n)-p;
    int m = 0;
    for (int i = 0; i < n; ++ i) {
        while (m > 1 && cro(ch[m-2], ch[m-1], p[i]) < flag) -- m;
        ch[m++] = p[i];
    }
    int temp = m;
    for (int i = n - 2; i >= 0; -- i) {
        while (m > temp && cro(ch[m-2], ch[m-1], p[i]) < flag) -- m;
        ch[m++] = p[i];
    }
    return m -= (n > 1);
}

//点在线段上(包含端点),在为 1 ,不在为 0
bool isPointOnSegment(Point P,Point A,Point B) {
    return cro(P, A, B) == 0 && dot(P, A, B) <= 0;  // 不包含端点时为 <0
}
//判断点在凸包内模板 O(logn)
//凸包为逆时针
//在边界,返回0,在内部,返回1,在外部,返回-1
int check(Point A, Point*p, int n ) {
    if (isPointOnSegment(A, p[0], p[1])) return 0; // 包含端点
    if (isPointOnSegment(A, p[0], p[n-1])) return 0;
    int l = 1, r = n - 2, mid;
    while (l <= r) {
        mid = l + r >> 1;
        ll a1 = cro(p[0], p[mid], A);
        ll a2 = cro(p[0], p[mid+1], A);
        if (a1 >= 0 && a2 <= 0) {
            ll tmp = cro(p[mid], p[mid+1], A);
            if (tmp > 0)return 1;
            if (tmp == 0) return 0;
            return -1;
        }
        else if (a1 < 0) r = mid - 1;
        else l = mid + 1;
    }
    return -1;
}

int Minkowski(Point *A, int n, Point *B, int m, Point *C){
    int t = 0, x = 1, y = 1;
    C[t++] = A[0] + B[0];
    A[n] = A[0], B[m] = B[0];
    while (x <= n && y <= m)
        if ( ((A[x]-A[x-1]) ^ (B[y]-B[y-1])) > 0)
            C[t] = C[t-1] + A[x] - A[x-1], t ++, x ++;
        else
            C[t] = C[t-1] + B[y] - B[y-1], t ++, y ++;
    while (x <= n) C[t] = C[t-1] + A[x] - A[x-1], t ++, x ++;
    while (y <= m) C[t] = C[t-1] + B[y] - B[y-1], t ++, y ++;
    return t - 1;
}

ll Area(Point *p, int n) {
    p[n] = p[0];
    ll area = 0;
    for (int i = 1; i < n-1; ++ i) {
        area += cro(p[0], p[i], p[i+1]);
    }
    return area;
}

int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int n, m;
    scanf("%d%d", &n, &m);

    for (int i = 0; i < n; ++ i) A[i].input();
    for (int i = 0; i < m; ++ i) B[i].input();
    n = ConvexHull(A, n, C);
    memcpy(A, C, sizeof(Point)*(n));
    m = ConvexHull(B, m, C);
    memcpy(B, C, sizeof(Point)*(m));

    int p = Minkowski(A, n, B, m, C);
    printf("%lld\n", Area(C, p));

    return 0;
}

 

posted @ 2021-03-09 16:46  ViKyanite  阅读(49)  评论(0编辑  收藏  举报