diff --git a/algorithms/geometry/convex_hull.cpp b/algorithms/geometry/convex_hull.cpp index b9fb75a6505b04888fc180e779db9947cca887a6..4f4f262a758541d6226d34d8b09f0c161e12dbf9 100644 --- a/algorithms/geometry/convex_hull.cpp +++ b/algorithms/geometry/convex_hull.cpp @@ -23,21 +23,21 @@ struct ConvexHull { */ int run(const vector<dd> &v) { int k = 0; - vector<int> ans(v.sz * 2); + vector<int> ans(v.size() * 2); - sort(v.begin(), v.end(), [](const dd &a, const dd &b) { + sort(all(v), [](const dd &a, const dd &b) { return (a.fi == b.fi) ? (a.se < b.se) : (a.fi < b.fi); }); // Uppermost part of convex hull - for (int i = 0; i < v.sz; ++i) { + for (int i = 0; i < v.size(); ++i) { while (k >= 2 && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0) k--; ans[k++] = i; } // Lowermost part of convex hull - for (int i = v.sz - 2, t = k + 1; i >= 0; --i) { + for (int i = v.size() - 2, t = k + 1; i >= 0; --i) { while (k >= t && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0) k--; ans[k++] = i; diff --git a/algorithms/geometry/geometry_functions.cpp b/algorithms/geometry/geometry_functions.cpp index 97b6abecaad422be0d0dddcfeda0a42512d3041f..0984d21092ec610ea469e9af326c4fd96bab4d97 100644 --- a/algorithms/geometry/geometry_functions.cpp +++ b/algorithms/geometry/geometry_functions.cpp @@ -2,21 +2,124 @@ * Geometry functions */ -struct Vector { - double x, y; +template <typename T> +struct Point { + T x, y; - Vector(double x, double y) : x(x), y(y) {} + Point(T x, T y) : x(x), y(y) {} - double dot_product(Vector v) { return x * v.x + y * v.y; } - double cross_product(Vector v) { return x * v.y - v.x * y; } + Point operator+(Point p) { return Point(x + p.x, y + p.y); } + Point operator-(Point p) { return Point(x - p.x, y - p.y); } + + T dot(Point p) { return (x * p.x) + (y * p.y); } + T cross(Point p) { return (x * p.y) - (y * p.y); } + + /** + * Returns angle between this and p: + * atan2(y, x) is in the range [-180,180]. To get [0, 360], + * atan2(-y, -x) + 180 is used + */ + T angle(Point p) { + return ((atan2(-cross(p), -dot(p)) * 180.0) / M_PI) + 180.0; + } + + /** + * Returns cosine value between this and p. + */ + T cosine(Point p) { + return (dot(p) / (sqrt(dot(*this)) * sqrt(p.dot(p)))); + } + + /** + * Returns sine value between this and p. + */ + T sine(Point p) { + return (cross(p) / (sqrt(dot(*this)) * sqrt(p.dot(p)))); + } + + /** + * Finds orientation of ordered triplet (a,b,c). + * 0 - Colinear; + * 1 - Clockwise; + * 2 - Counterclockwise. + */ + static int orientation(Point a, Point b, Point c) { + T val = (b - a).cross(c - b); + + if (val == 0) + return 0; + + return (val > 0) ? 1 : 2; + } +}; + +template <typename T> +struct Segment { + Point<T> a, b; + + Segment(Point a, Point b) : a(a), b(b) {} + + /** + * Checks if points p and q are on the same side of the segment. + */ + bool same_side(Point p, Point q) { + T cpp = (p - a).cross(b - a); + T cpq = (q - a).cross(b - a); + return ((cpp > 0 && cpq > 0) || (cpp < 0 && cpq < 0)); + } + + /** + * Checks if point p is on the segment. + */ + bool on_segment(Point p) { + return (p.x <= max(a.x, b.x) && + p.x >= min(a.x, b.x) && + p.y <= max(a.y, b.y) && + p.y >= min(a.y, b.y)); + } + + /** + * Checks if segment intersects with s. + */ + bool intersect(Segment s) { + int o1 = Point::orientation( a, b, s.a); + int o2 = Point::orientation( a, b, s.b); + int o3 = Point::orientation(s.a, s.b, a); + int o4 = Point::orientation(s.a, s.b, b); + + if (o1 != o2 && o3 != o4) + return true; + + if (o1 == 0 && on_segment(s.a)) return true; + if (o2 == 0 && on_segment(s.b)) return true; + if (o3 == 0 && s.on_segment(a)) return true; + if (o4 == 0 && s.on_segment(b)) return true; + + return false; + } +}; + +template <typename T> +struct Polygon { + vector<Point<T>> vertices; + + Polygon() {} + Polygon(vector<Point> vertices) : vertices(vertices) {} + + /** + * Adds a vertex to the polygon. + */ + void add_point(Point p) { vertices.pb(p); } /** - * Returns angle between this and v. + * Returns area of polygon (only works when vertices are sorted in clockwise + * or counterclockwise order). */ - double angle(Vector v) { + double area() { + double ans = 0; + for (int i = 0; i < vertices.size(); ++i) + ans += vertices[i].cross(vertices[(i + 1) % vertices.size()]); - // atan2(y, x) is in the range [-180,180]. To get [0, 360], - // atan2(-y, -x) + 180 is used - return ((atan2(-cross_product(v), -dot_product(v)) * 180.0) / M_PI) + 180.0; + return fabs(ans) / 2.0; } }; diff --git a/algorithms/graph/lca.cpp b/algorithms/graph/lca.cpp index b3faae5429289293dbdbf10a7ef51a7190125917..136a2c051095c20b64175eba8278a581a01f4a9a 100644 --- a/algorithms/graph/lca.cpp +++ b/algorithms/graph/lca.cpp @@ -50,7 +50,7 @@ struct LCA { */ void preprocess(int v) { mset(par, -1); - //*** mset(cost, 0; + //*** mset(cost, 0); dfs(v); }