Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Слава Україні, Героям слава
- #include <bits/stdc++.h>
- using namespace std;
- using ll = long long;
- struct point {
- ll x, y;
- point(ll x_ = 0, ll y_ = 0) : x(x_), y(y_) {}
- point operator -(point p) {
- return point(x - p.x, y - p.y);
- }
- bool operator == (const point &p) const {
- return x == p.x and y == p.y;
- }
- bool operator < (const point &p) const {
- return (x < p.x) or (x == p.x and y < p.y);
- }
- ll operator %(point p) {
- return x * p.y - y * p.x;
- }
- bool on_seg(point p, point q) {
- if(this->dir(p, q)) return false;
- return (x > min(p.x, q.x)) and (x < max(p.x, q.x)) and (y > min(p.y, q.y)) and (y < max(p.y, q.y));
- }
- long double dist (const point &p) const {
- return hypotl(x - p.x, y - p.y);
- }
- ll dist2 (const point &p) const {
- return (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y);
- }
- int dir(point origin, point other) {
- ll d = (*this - origin) % (other - origin);
- return (d > 0) - (d < 0);
- }
- };
- ll cross(point p, point q) {
- return p.x * q.y - p.y * q.x;
- }
- ll area_2(point a, point b, point c) {
- return cross(a, b) + cross(b, c) + cross(c, a);
- }
- void monotone_hull(vector<point> &pts) {
- sort(pts.begin(), pts.end());
- pts.erase(unique(pts.begin(), pts.end()), pts.end());
- vector<point> up, dn;
- for(int i = 0; i < pts.size(); i++) {
- while(up.size() > 1 and area_2(up[up.size() - 2], up.back(), pts[i]) > 0) up.pop_back();
- while(dn.size() > 1 and area_2(dn[dn.size() - 2], dn.back(), pts[i]) < 0) dn.pop_back();
- dn.push_back(pts[i]);
- up.push_back(pts[i]);
- }
- pts = dn;
- for(int i = (int)up.size() - 2; i >= 1; i--) {
- pts.push_back(up[i]);
- }
- }
- int direction(point origin, point p, point other) {
- return p.dir(origin, other);
- }
- bool segment_segment_intersect(point a, point b, point c, point d) {
- if(a.dist2(c) == 0 or a.dist2(d) == 0 or b.dist2(c) == 0 or b.dist2(d) == 0) return true;
- ll d1 = direction(a, b, c);
- ll d2 = direction(a, b, d);
- ll d3 = direction(c, d, a);
- ll d4 = direction(c, d, b);
- if(d1 * d2 < 0 and d3 * d4 < 0) return true;
- return a.on_seg(c, d) or b.on_seg(c, d) or c.on_seg(a, b) or d.on_seg(a, b);
- }
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- cout << setprecision(6) << fixed;
- int t;
- cin >> t;
- while(t--) {
- int n;
- cin >> n;
- vector<pair<array<point, 4>, int>> v(n);
- vector<point> pts;
- for(auto &[arr, h] : v) {
- for(int i = 0; i < 4; i++) {
- cin >> arr[i].x >> arr[i].y;
- pts.emplace_back(arr[i]);
- }
- cin >> h;
- }
- monotone_hull(pts);
- long double perimeter = 0;
- for(int i = 0; i < (int)pts.size(); i++) {
- perimeter += pts[i].dist(pts[(i + 1) % pts.size()]);
- }
- int h = 3;
- for(int i = 0; i < (int)pts.size(); i++) for(int j = i + 1; j < (int)pts.size(); j++) {
- for(int k = 0; k < n; k++) {
- for(int ii = 0; ii < 4; ii++) for(int jj = ii + 1; jj < 4; jj++) {
- if(segment_segment_intersect(pts[i], pts[j], v[k].first[ii], v[k].first[jj])) {
- h = max(h, v[k].second + 1);
- }
- }
- }
- }
- cout << perimeter << " " << h << "\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment