using ld = long double; using pdd = pair; using line = pair; // half plane : left side of vector fi->se const ld eps = 1e-9; pdd operator*(const pdd& a, ld s) { return {a.fi * s, a.se * s}; } inline bool equals(ld a, ld b) { return abs(a - b) < eps; } bool line_intersect(line& a, line& b, pdd& v) { ld det = (a.se - a.fi) / (b.se - b.fi); if (equals(det, 0)) return 0; ld t = ((b.fi - a.fi) / (b.se - b.fi)) / det; v = a.fi + (a.se - a.fi) * t; return 1; } bool bad(line& a, line& b, line& c) { pdd v; if(!line_intersect(a, b, v)) return 0; return (c.se - c.fi) / (v - c.fi) <= eps; } vector HPI(vector& lns) { auto lsgn = [&](const line& a) { if(a.fi.se == a.se.se) return a.fi.fi > a.se.fi; return a.fi.se > a.se.se; }; sort(lns.begin(), lns.end(), [&](const line& a, const line& b) { if(lsgn(a) != lsgn(b)) return lsgn(a) < lsgn(b); return (a.se - a.fi) / (b.se - b.fi) > 0; }); deque dq; for(auto l : lns){ while(dq.size() >= 2 && bad(dq[dq.size()-2], dq.back(), l)) dq.pop_back(); while(dq.size() >= 2 && bad(dq[0], dq[1], l)) dq.pop_front(); if(dq.size() < 2 || !bad(dq.back(), l, dq[0])) dq.pb(l); } vector res; if(dq.size() >= 3) { for(int i = 0; i < (int)dq.size(); i++) { int j = (i + 1) % (int)dq.size(); pdd v; if(!line_intersect(dq[i], dq[j], v)) continue; res.push_back(v); } } return res; }