凸包
using ll = long long;
struct Point {
ll x, y;
bool operator<(const Point &other) const {
if (x != other.x) return x < other.x;
return y < other.y;
}
bool operator==(const Point &other) const {
return x == other.x && y == other.y;
}
};
ll cross(const Point &O, const Point &A, const Point &B) {
return (A.x - O.x) * (B.y - O.y)
- (A.y - O.y) * (B.x - O.x);
}
// 求凸包
// keep_collinear = false:不保留边上的中间共线点
// keep_collinear = true :保留凸包边界上的共线点
vector<Point> convexHull(vector<Point> p, bool keep_collinear = false) {
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
int n = p.size();
if (n <= 1) {
return p;
}
vector<Point> hull;
// 下凸壳
for (const auto &point : p) {
while (hull.size() >= 2) {
ll c = cross(hull[hull.size() - 2],
hull[hull.size() - 1],
point);
if (keep_collinear ? c < 0 : c <= 0) {
hull.pop_back();
} else {
break;
}
}
hull.push_back(point);
}
// 上凸壳
int lower_size = hull.size();
for (int i = n - 2; i >= 0; --i) {
while ((int)hull.size() > lower_size) {
ll c = cross(hull[hull.size() - 2],
hull[hull.size() - 1],
p[i]);
if (keep_collinear ? c < 0 : c <= 0) {
hull.pop_back();
} else {
break;
}
}
hull.push_back(p[i]);
}
hull.pop_back();
return hull;
}
haze

浙公网安备 33010602011771号