sgu 277 水平序动态凸包

mac2024-03-31  31

用整形实现的。封装好了。就是不知道为什么有点慢。

code(373ms):

#include <iostream> #include <set> using namespace std; #define DEBUG 0 typedef long long LL; typedef LL LT; template <typename T> T sq(T x) { return x * x; } int sgn(LT x) { return x < 0 ? -1 : (x > 0 ? 1 : 0); } struct VEC { LT x, y; VEC operator + (const VEC& b) const { return VEC{x + b.x, y + b.y}; } bool operator == (const VEC& b) const { return x == b.x && y == b.y; } bool operator < (const VEC& b) const { return y != b.y ? y < b.y : x < b.x; } VEC operator - (const VEC& b) const { return VEC{x - b.x, y - b.y}; } LT len2() const { return sq(x) + sq(y); } LT dist2(const VEC& b) const { return (*this - b).len2(); } //Might overflow LT operator * (const VEC& b) const { return x * b.x + y * b.y; } LT operator ^ (const VEC& b) const { return x * b.y - y * b.x; } bool ToLeftTest(const VEC& b) const { return (*this ^ b) > 0; } bool ToRightTest(const VEC& b) const { return (*this ^ b) < 0; } LT cross(const VEC& p1, const VEC& p2) const { return (p1 - *this) ^ (p2 - *this); } void input() { cin >> x >> y; } }; struct down_sgn { int operator () (LT x) const { return sgn(x); } }; struct up_sgn { int operator () (LT x) const { return -sgn(x); } }; template <class XSGN> struct HalfConvexHull { #define xsgn XSGN() struct CMPX { bool operator () (const VEC& a, const VEC& b) { return xsgn(a.x - b.x) < 0; } }; typedef set<VEC, CMPX> SE; SE s; typedef typename SE::iterator IT; LT area2; //to (0, 0) IT it; HalfConvexHull() : area2(0) {} //The convex mustn't be degenerate //0: out //1: on //2: in int relation(const VEC& p) { it = s.lower_bound(p); if (it == s.end()) return 0; if (it == s.begin()) { if (xsgn(p.x - it->x) < 0) return 0; else return xsgn(p.y - it->y) + 1; } auto bef = it; --bef; return sgn((*it - *bef) ^ (p - *bef)) + 1; } IT Pre(IT it) { return it == s.begin() ? s.end() : --it; } void Insert(const VEC& p) { if (relation(p)) return; bool del = false; VEC d; if (it != s.end() && it->x == p.x) { d = *it; del = true; s.erase(it); } it = s.insert(p).first; auto pre = Pre(it); auto nxt(it); ++nxt; if (pre != s.end()) { if (del) { area2 -= *pre ^ d; } else if (nxt != s.end()) { area2 -= *pre ^ *nxt; } area2 += *pre ^ p; for (auto j = Pre(pre); j != s.end() && ((*pre - p) ^ (*j - p)) >= 0; pre = j, j = Pre(j)) { area2 += (*j ^ p) - (*j ^ *pre) - (*pre ^ p); s.erase(pre); } } if (nxt != s.end()) { if (del) { area2 -= d ^ *nxt; } area2 += p ^ *nxt; auto j = nxt; for (++j; j != s.end() && ((*j - p) ^ (*nxt - p)) >= 0; nxt = j, ++j) { area2 += (p ^ *j) - (p ^ *nxt) - (*nxt ^ *j); s.erase(nxt); } } } }; struct ConvexHull { HalfConvexHull<down_sgn> down; HalfConvexHull<up_sgn> up; void Insert(const VEC& p) { down.Insert(p); up.Insert(p); } LT area2() const { if (down.s.empty()) return 0; return (*up.s.rbegin() ^ *down.s.begin()) + down.area2 + (*down.s.rbegin() ^ *up.s.begin()) + up.area2; } }; int main() { ConvexHull conv; VEC p; ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n = 3; while (n--) { p.input(); conv.Insert(p); } cin >> n; while (n--) { if (0 == n) { n = n * 2 / 2; } p.input(); conv.Insert(p); cout << conv.area2() << endl; } return 0; }
最新回复(0)