模板题,T了最后三个点

P4557 [JSOI2018] 战争

@[阿尔托莉雅丶](/user/105820) 线性查找肯定不行啊,有 $\log$ 做法为什么不用呢 ```cpp template <typename _Tp> struct point { _Tp x, y; inline point(const _Tp& xx, const _Tp& yy) : x(xx), y(yy) {} inline point() {} inline point(const std::pair<_Tp, _Tp>& pr) : x(pr.first), y(pr.second) {} inline point<_Tp>& operator=(const point<_Tp>& p) { x = p.x; y = p.y; return *this; } inline bool operator==(const point<_Tp>& o) const { return x == o.x && y == o.y; } friend inline double dist(const point<_Tp>& a, const point<_Tp>& b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } friend inline _Tp dist_sqr(const point<_Tp>& a, const point<_Tp>& b) { return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); } inline _Tp dist_sqr() const { return x * x + y * y; } inline point<_Tp> operator+(const point<_Tp>& p) const { return point<_Tp>(x + p.x, y + p.y); } inline point<_Tp> operator-(const point<_Tp>& p) const { return point<_Tp>(x - p.x, y - p.y); } inline _Tp operator*(const point<_Tp>& p) const { return x * p.y - y * p.x; } template <typename _Istream> friend inline _Istream& operator>>(_Istream& is, point<_Tp>& p) { return is >> p.x >> p.y; } operator std::pair<_Tp, _Tp>() const { return std::make_pair(x, y); } }; template <typename _Tp, typename _Alloc = std::allocator<_Tp> > class convex_hull { public: typedef point<_Tp> value_type; typedef const point<_Tp>& reference; typedef const point<_Tp>& const_reference; typedef const point<_Tp>* pointer; typedef const point<_Tp>* const_pointer; typedef typename std::allocator_traits<_Alloc>::template rebind_alloc<point<_Tp> > allocator_type; typedef typename std::vector<point<_Tp>, allocator_type>::size_type size_type; typedef typename std::vector<point<_Tp>, allocator_type>::difference_type difference_type; typedef typename std::vector<point<_Tp>, allocator_type>::const_iterator iterator; typedef typename std::vector<point<_Tp>, allocator_type>::const_iterator const_iterator; typedef typename std::vector<point<_Tp>, allocator_type>::const_reverse_iterator reverse_iterator; typedef typename std::vector<point<_Tp>, allocator_type>::const_reverse_iterator const_reverse_iterator; private: typedef std::less<_Tp> _Comp; std::vector<point<_Tp>, allocator_type> _M_vec; static inline _Comp _M_comp{}; static constexpr double _S_eps = 1e-5; public: static inline bool cmp1(const point<_Tp>& a, const point<_Tp>& b) { return a.y == b.y ? _M_comp(a.x, b.x) : _M_comp(a.y, b.y); } static inline bool cmp2(const point<_Tp>& a, const point<_Tp>& b) { return _M_comp(_Tp(), a * b) || (!_M_comp(a * b, _Tp()) && _M_comp(a.dist_sqr(), b.dist_sqr())); } static inline int _S_sign(double v) { return v < -_S_eps ? -1 : (_S_eps < v ? 1 : 0); } private: template <typename _O_alloc> static inline void _S_convex(std::vector<point<_Tp>, _O_alloc>& vec) { const size_t n = vec.size(); if (n <= 2) return; std::sort(vec.begin(), vec.end(), cmp1); std::vector<size_t, typename std::allocator_traits<_Alloc>::template rebind_alloc<size_t> > stk; point<_Tp> p = vec[0]; for (size_t i = 0; i < n; i++) vec[i] = vec[i] - p; auto tmp = vec.begin(); std::sort(++tmp, vec.end(), cmp2); size_t top = 0; stk.resize(n + 1); stk[++top] = 0; for (int i = 1; i < n; i++) { while (top > 1 && !_M_comp((vec[i] - vec[stk[top - 1]]) * (vec[stk[top]] - vec[stk[top - 1]]), _Tp())) --top; stk[++top] = i; } std::vector<point<_Tp>, _O_alloc> ret; for (size_t i = 1; i <= top; i++) ret.push_back(vec[stk[i]] + p); vec = ret; } template <typename _O_alloc> static inline _Tp _S_diameter(const std::vector<point<_Tp>, _O_alloc>& vec) { const size_t n = vec.size(); _Tp ans = (vec[1] - vec[0]).dist_sqr(); if (n == 2) return ans; for (size_t i = 0, j = 2; i < n; i++) { while (_S_sign(fabs((double)((vec[(i + 1) % n] - vec[i]) * (vec[j] - vec[i]))) - fabs((double)((vec[(i + 1) % n] - vec[i]) * (vec[(j + 1) % n] - vec[i])))) < 0) j = (j + 1) % n; ans = std::max(ans, std::max((vec[j] - vec[i]).dist_sqr(), (vec[j] - vec[(i + 1) % n]).dist_sqr(), _M_comp), _M_comp); } return ans; } public: inline convex_hull() = default; inline convex_hull(const std::vector<point<_Tp>, allocator_type>& vec) : _M_vec(vec) { _S_convex(_M_vec); } inline operator std::vector<point<_Tp>, allocator_type>() const { return _M_vec; } inline iterator begin() { return _M_vec.begin(); } inline iterator end() { return _M_vec.end(); } inline const_iterator begin() const { return _M_vec.begin(); } inline const_iterator end() const { return _M_vec.end(); } inline const_iterator cbegin() const { return _M_vec.cbegin(); } inline const_iterator cend() const { return _M_vec.cend(); } inline reverse_iterator rbegin() { return _M_vec.rbegin(); } inline reverse_iterator rend() { return _M_vec.rend(); } inline const_reverse_iterator rbegin() const { return _M_vec.rbegin(); } inline const_reverse_iterator rend() const { return _M_vec.rend(); } inline const_reverse_iterator crbegin() const { return _M_vec.crbegin(); } inline const_reverse_iterator crend() const { return _M_vec.crend(); } inline point<_Tp>* data() { return _M_vec.data(); } inline const point<_Tp>* data() const { return _M_vec.data(); } inline size_type size() const { return _M_vec.size(); } inline bool empty() const { return _M_vec.empty(); } inline void clear() { _M_vec.clear(); } inline void reserve(size_type n) { _M_vec.reserve(n); } inline const_reference operator[](size_type n) const { return _M_vec[n]; } inline const_reference at(size_type n) const { return _M_vec.at(n); } inline void push_back(const point<_Tp>& p) { if (_M_vec.empty()) { _M_vec.push_back(p); return; } _M_vec.push_back(p); _S_convex(_M_vec); } template <typename... _Args> inline void emplace_back(_Args&&... args) { _M_vec.emplace_back(args...); _S_convex(_M_vec); } inline double diameter() const { return sqrt((double)_S_diameter(_M_vec)); } inline _Tp diameter_sqr() const { return _S_diameter(_M_vec); } inline void merge(const convex_hull<_Tp, _Alloc>& b) { size_t n = size(), m = b.size(); decltype(_M_vec) A, B; for (size_t i = 0; i < n; i++) A.push_back(_M_vec[(i + 1) % n] - _M_vec[i]); for (size_t i = 0; i < m; i++) B.push_back(b[(i + 1) % m] - b[i]); decltype(_M_vec) res; size_t i = 0, j = 0, cnt = 0; res.push_back(_M_vec[0] + b[0]); while (i < n && j < m) { res.push_back(res[cnt] + (_S_sign(A[i] * B[j]) >= 0 ? A[i++] : B[j++])); ++cnt; } while (i < n) { res.push_back(res[cnt] + A[i++]); ++cnt; } while (j < m) { res.push_back(res[cnt] + B[j++]); ++cnt; } _M_vec = res; _S_convex(_M_vec); } inline bool inside(const point<_Tp>& poi) const { point<_Tp> t = _M_vec[0]; if (_S_sign((poi - t) * (_M_vec[0] - t)) > 0 || _S_sign((*_M_vec.rbegin() - t) * (poi - t)) > 0) return false; iterator p = std::lower_bound(_M_vec.begin(), _M_vec.end(), poi, [=](const point<_Tp>& a, const point<_Tp>& b) { return cmp2(a - t, b - t); }); --p; point<_Tp> i = *p, j; ++p; if (p == _M_vec.end()) j = _M_vec[0]; else j = *p; return _S_sign((poi - i) * (j - i)) <= 0; } }; ```
by Ruiqun2009 @ 2022-12-10 23:02:01


|