4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: //------------------------------------------------------------- 4fd800b3a8 2011-02-23 kinaba: // Convex Hull -- Andrew's Monotone Chain 4fd800b3a8 2011-02-23 kinaba: // O(N log N) 4fd800b3a8 2011-02-23 kinaba: // 4fd800b3a8 2011-02-23 kinaba: // Verified by 4fd800b3a8 2011-02-23 kinaba: // - SRM 336 Div1 LV3 4fd800b3a8 2011-02-23 kinaba: // - TCO09 Round2 LV2 4fd800b3a8 2011-02-23 kinaba: // - SRM 486 Div1 LV3 4fd800b3a8 2011-02-23 kinaba: //------------------------------------------------------------- 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: double outer_prod(const CMP& a, const CMP& b) { return imag(conj(a)*b); } 4fd800b3a8 2011-02-23 kinaba: double inner_prod(const CMP& a, const CMP& b) { return real(conj(a)*b); } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: int ccw(const CMP& a, CMP b, CMP c) { 4fd800b3a8 2011-02-23 kinaba: b -= a; c -= a; 4fd800b3a8 2011-02-23 kinaba: if( outer_prod(b,c) > 0 ) return +1; // counter clockwise 4fd800b3a8 2011-02-23 kinaba: if( outer_prod(b,c) < 0 ) return -1; // clockwise 4fd800b3a8 2011-02-23 kinaba: if( inner_prod(b,c) < 0 ) return +2; // c--a--b on line 4fd800b3a8 2011-02-23 kinaba: if( norm(b) < norm(c) ) return -2; // a--b--c on line 4fd800b3a8 2011-02-23 kinaba: return 0; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: bool byX( const CMP& a, const CMP& b ) { 4fd800b3a8 2011-02-23 kinaba: if( a.real() != b.real() ) 4fd800b3a8 2011-02-23 kinaba: return a.real() < b.real(); 4fd800b3a8 2011-02-23 kinaba: return a.imag() < b.imag(); 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: vector<CMP> convex_hull( vector<CMP> p ) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: #define IS_RIGHT <0 // skip on-line verts 4fd800b3a8 2011-02-23 kinaba: //#define IS_RIGHT ==-1 // take all 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: sort(p.begin(), p.end(), &byX); 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: vector<CMP> ans; 4fd800b3a8 2011-02-23 kinaba: for(int i=0; i<p.size(); ans.push_back(p[i++])) // left-to-right 4fd800b3a8 2011-02-23 kinaba: while( ans.size()>=2 && ccw(ans[ans.size()-2], ans[ans.size()-1], p[i]) IS_RIGHT ) 4fd800b3a8 2011-02-23 kinaba: ans.pop_back(); 4fd800b3a8 2011-02-23 kinaba: if( ans.size() == p.size() ) 4fd800b3a8 2011-02-23 kinaba: return ans; 4fd800b3a8 2011-02-23 kinaba: for(int i=p.size()-2; i>=0; ans.push_back(p[i--])) // right-to-left 4fd800b3a8 2011-02-23 kinaba: while( ans.size()>=2 && ccw(ans[ans.size()-2], ans[ans.size()-1], p[i]) IS_RIGHT ) 4fd800b3a8 2011-02-23 kinaba: ans.pop_back(); 4fd800b3a8 2011-02-23 kinaba: ans.pop_back(); 4fd800b3a8 2011-02-23 kinaba: return ans; 4fd800b3a8 2011-02-23 kinaba: }