#include<bits/stdc++.h> #define ll long long // Usage: // ConvexHull hull; // hull.addPoint(x, y); // convexhull = hull.getConvexHull(); struct ConvexHull { struct Point { double x, y; Point(){} Point(double _1, double _2) : x(_1), y(_2) {} bool operator < (Point b) const { if (x != b.x) return x < b.x; return y < b.y; } }; vector<Point> a; set<Point> bag; ConvexHull () { a.clear(); bag.clear(); } void clear() { a.clear(); bag.clear(); } bool cw(Point a, Point b, Point c) { return a.x*(b.y-c.y) + b.x*(c.y-a.y) + c.x*(a.y-b.y) < 0; } bool ccw(Point a, Point b, Point c) { return a.x*(b.y-c.y) + b.x*(c.y-a.y) + c.x*(a.y-b.y) > 0; } void addPoint(double x, double y) { bag.insert(Point(x, y)); } vector< pair<double, double> > getConvexHull() { // take all points from set to vector, sorted by increasing order for (auto it = bag.begin(); it != bag.end(); ++it) a.push_back(*it); vector< pair<double, double> > hull; if (a.size() <= 1) { for (auto p : a) hull.push_back({p.x, p.y}); return hull; } Point p1 = a[0], p2 = a.back(); vector<Point> up, down; up.push_back(p1); down.push_back(p1); for (int i = 1; i < a.size(); i++) { if (i == a.size() - 1 || cw(p1, a[i], p2)) { while (up.size() >= 2 && !cw(up[up.size()-2], up[up.size()-1], a[i])) up.pop_back(); up.push_back(a[i]); } if (i == a.size() - 1 || ccw(p1, a[i], p2)) { while(down.size() >= 2 && !ccw(down[down.size()-2], down[down.size()-1], a[i])) down.pop_back(); down.push_back(a[i]); } } for (int i = 0; i < up.size(); i++) hull.push_back({up[i].x, up[i].y}); for (int i = down.size() - 2; i > 0; i--) hull.push_back({down[i].x, down[i].y}); return hull; } };