diff --git a/contests/Cadernaveis/URI1464.cpp b/contests/Cadernaveis/URI1464.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b6b120bccb403e595ed270ffaae4e5723c04369 --- /dev/null +++ b/contests/Cadernaveis/URI1464.cpp @@ -0,0 +1,80 @@ +#include <bits/stdc++.h> + +#define MAX 0 +#define MOD 1000000007 +#define inf 0x3f3f3f3f + +#define fi first +#define se second +#define sz size() +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() + +using namespace std; + +typedef long long ll; +typedef pair<int,int> ii; +typedef pair<double,double> dd; + + +double cross(dd a, dd b, dd c) { + return (b.fi - a.fi) * (c.se - a.se) - (b.se - a.se) * (c.fi - a.fi); +} + + +int convex_hull(vector<dd> &v) { + int k = 0; + vector<int> ans(v.sz * 2); + + sort(v.begin(), v.end(), [](const dd &a, const dd &b) -> bool { + return (a.fi == b.fi) ? (a.se < b.se) : (a.fi < b.fi); + }); + + for (int i = 0; i < v.sz; ++i) { + while (k >= 2 && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0) k--; + ans[k++] = i; + } + + for (int i = v.sz - 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; + } + + ans.resize(k); + sort(rall(ans)); + ans.erase(unique(all(ans)), ans.end()); + + for (auto i : ans) + v.erase(v.begin() + i); + + return k - 1; +} + + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + int n; + while (cin >> n && n) { + vector<dd> v; + double x, y; + + for (int i = 0; i < n; ++i) { + cin >> x >> y; + v.pb(dd(x, y)); + } + + int ans = 0; + while (v.sz) { + convex_hull(v); + ans++; + } + + if (ans % 2) cout << "Take this onion to the lab!\n"; + else cout << "Do not take this onion to the lab!\n"; + } + + return 0; +} diff --git a/geometry/convex_hull.cpp b/geometry/convex_hull.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a10e96b6ffbeaebf6202eb097addfbd6f692b58 --- /dev/null +++ b/geometry/convex_hull.cpp @@ -0,0 +1,49 @@ +/** + * Convex Hull + * + * Complexity (Time): O(n log n) + * Complexity (Space): O(n) + */ + +typedef pair<double,double> dd; + +// The three points are a counter-clockwise turn if cross > 0, clockwise if +// cross < 0, and collinear if cross = 0 +double cross(dd a, dd b, dd c) { + return (b.fi - a.fi) * (c.se - a.se) - (b.se - a.se) * (c.fi - a.fi); +} + + +// Find, among v, the points that form a convex hull +int convex_hull(const vector<dd> &v) { + int k = 0; + vector<int> ans(v.sz * 2); + + // Sort points + sort(v.begin(), v.end(), [](const dd &a, const dd &b) -> bool { + 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) { + 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) { + while (k >= t && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0) k--; + ans[k++] = i; + } + + // The ans vector contains the indices (relative to the sorted vector!) of + // the points belonging to the convex hull + ans.resize(k); + + // Remove duplicates + sort(all(ans)); + ans.erase(unique(all(ans)), ans.end()); + + // Returns amount of point in the convex hull + return k - 1; +}