Problem p00960 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

using D = double;
const D PI = acos(D(-1)), EPS = 1e-10;

struct Pt2 {
  D x, y;
  Pt2() {}
  Pt2(D _x, D _y) : x(_x), y(_y) {}
  Pt2 operator+(const Pt2 &r) const { return Pt2(x + r.x, y + r.y); }
  Pt2 operator-(const Pt2 &r) const { return Pt2(x - r.x, y - r.y); }
  Pt2 operator*(const Pt2 &r) const {
    return Pt2(x * r.x - y * r.y, x * r.y + y * r.x);
  }
  Pt2 &operator+=(const Pt2 &r) { return *this = *this + r; }
  Pt2 &operator-=(const Pt2 &r) { return *this = *this - r; }
  Pt2 &operator*=(const Pt2 &r) { return *this = *this * r; }

  Pt2 operator-() const { return Pt2(-x, -y); }

  D abs() const { return sqrt(x * x + y * y); }
  D rabs() const { return max(x, y); } // robust abs
  D arg() const { return atan2(y, x); }

  pair<D, D> to_pair() const { return make_pair(x, y); }
  static Pt2 polar(D le, D th) { return Pt2(le * cos(th), le * sin(th)); }
};
template <class T> ostream &operator<<(ostream &os, const Pt2 &p) {
  os << "(" << p.x << ", " << p.y << ")";
  return os;
}
using P = Pt2;

int sgn(D a) {
  if (abs(a) <= EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
// relative sign
int rsgn(D a, D f) {
  if (abs(a) <= f * EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
bool near(P a, P b) { return !sgn((a - b).abs()); }

bool lessP(P l, P r) {
  if (sgn(r.x - l.x))
    return l.x < r.x;
  if (sgn(r.y - l.y))
    return l.y < r.y;
  return false;
}

D cross(P a, P b) { return a.x * b.y - a.y * b.x; }
D dot(P a, P b) { return a.x * b.x + a.y * b.y; }

// -2, -1, 0, 1, 2 : front, clock, on, cclock, back
int ccw(P b, P c) {
  int s = rsgn(cross(b, c), b.rabs());
  if (s)
    return s;
  if (!sgn(c.rabs()) || !sgn((c - b).rabs()))
    return 0;
  if (dot(b, c) < 0)
    return 2;
  if (dot(-b, c - b) < 0)
    return -2;
  return 0;
}
int ccw(P a, P b, P c) { return ccw(b - a, c - a); }

using Pol = V<P>;

Pol convex_up(const Pol &p, int l, int r, int e1 = -1, int e2 = -1) {
  Pol up;
  for (int i = l; i <= r; i++) {
    if (i == e1 || i == e2)
      continue;
    P d = p[i];
    while (up.size() > 1 && ccw(up[up.size() - 2], up[up.size() - 1], d) == 1)
      up.pop_back();
    up.push_back(d);
  }
  return up;
}

Pol convex_down(const Pol &p, int l, int r, int e1 = -1, int e2 = -1) {
  Pol down;
  for (int i = l; i <= r; i++) {
    if (i == e1 || i == e2)
      continue;
    P d = p[i];
    while (down.size() > 1 &&
           ccw(down[down.size() - 2], down[down.size() - 1], d) == -1)
      down.pop_back();
    down.push_back(d);
  }
  return down;
}

D line_len(const Pol &p) {
  int n = int(p.size());
  D sm = 0;
  for (int i = 0; i < n - 1; i++) {
    sm += (p[i + 1] - p[i]).abs();
  }
  return sm;
}

bool operator<(const P &x, const P &y) { return lessP(x, y); }

D solve(V<P> v, bool one = false) {
  int n = int(v.size());
  map<P, int> mp;
  for (int i = 0; i < n; i++)
    mp[v[i]] = i;

  auto up = convex_up(v, 0, n - 1);
  auto down = convex_down(v, 0, n - 1);

  int un = int(up.size()), dn = int(down.size());
  V<D> bufu, bufd;
  for (int i = 1; i < un - 1; i++) {
    D base = (up[i - 1] - up[i]).abs() + (up[i] - up[i + 1]).abs();
    bufu.push_back(
        base - line_len(convex_up(v, mp[up[i - 1]], mp[up[i + 1]], mp[up[i]])));
  }

  for (int i = 1; i < dn - 1; i++) {
    D base = (down[i - 1] - down[i]).abs() + (down[i] - down[i + 1]).abs();
    bufd.push_back(base - line_len(convex_down(v, mp[down[i - 1]],
                                               mp[down[i + 1]], mp[down[i]])));
  }

  D ans = -1e100;
  D uma = -1e100, dma = -1e100;
  for (int i = 1; i < un - 2; i++) {
    ans = max(ans, uma + bufu[i]);
    uma = max(uma, bufu[i - 1]);
  }
  for (int i = 1; i < dn - 2; i++) {
    ans = max(ans, dma + bufu[i]);
    dma = max(dma, bufu[i - 1]);
  }
  for (auto d : bufu)
    uma = max(uma, d);
  for (auto d : bufd)
    dma = max(dma, d);

  if (one)
    return max(uma, dma);

  ans = max(ans, uma + dma);

  for (int i = 1; i < un - 1; i++) {
    D base = (up[i - 1] - up[i]).abs() + (up[i] - up[i + 1]).abs();
    auto npo = convex_up(v, mp[up[i - 1]], mp[up[i + 1]], mp[up[i]]);
    base -= line_len(npo);
    int m = int(npo.size());
    for (int j = 1; j < m - 1; j++) {
      D base2 = (npo[j - 1] - npo[j]).abs() + (npo[j] - npo[j + 1]).abs();
      ans = max(ans, base + base2 -
                         line_len(convex_up(v, mp[npo[j - 1]], mp[npo[j + 1]],
                                            mp[npo[j]], mp[up[i]])));
    }
  }

  for (int i = 1; i < dn - 1; i++) {
    D base = (down[i - 1] - down[i]).abs() + (down[i] - down[i + 1]).abs();
    auto npo = convex_down(v, mp[down[i - 1]], mp[down[i + 1]], mp[down[i]]);
    base -= line_len(npo);
    int m = int(npo.size());
    for (int j = 1; j < m - 1; j++) {
      D base2 = (npo[j - 1] - npo[j]).abs() + (npo[j] - npo[j + 1]).abs();
      ans = max(ans, base + base2 -
                         line_len(convex_down(v, mp[npo[j - 1]], mp[npo[j + 1]],
                                              mp[npo[j]], mp[down[i]])));
    }
  }

  for (int i = 1; i < un - 2; i++) {
    D base = (up[i - 1] - up[i]).abs() + (up[i] - up[i + 1]).abs() +
             (up[i + 1] - up[i + 2]).abs();
    ans = max(ans, base - line_len(convex_up(v, mp[up[i - 1]], mp[up[i + 2]],
                                             mp[up[i]], mp[up[i + 1]])));
  }
  for (int i = 1; i < dn - 2; i++) {
    D base = (down[i - 1] - down[i]).abs() + (down[i] - down[i + 1]).abs() +
             (down[i + 1] - down[i + 2]).abs();
    ans = max(ans,
              base - line_len(convex_down(v, mp[down[i - 1]], mp[down[i + 2]],
                                          mp[down[i]], mp[down[i + 1]])));
  }

  return ans;
}

D naive(V<P> v) {
  int n = int(v.size());
  auto up = convex_up(v, 0, n - 1);
  auto down = convex_down(v, 0, n - 1);

  return line_len(up) + line_len(down);
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);

  int n;
  cin >> n;
  V<P> v(n);
  for (int i = 0; i < n; i++) {
    D x, y;
    cin >> x >> y;
    v[i] = P(x, y);
    v[i] *= P::polar(1, 13.4514);
  }
  sort(begin(v), end(v));

  D ma = -1;
  D base = naive(v);
  ma = max(ma, base - naive(V<P>(begin(v), end(v) - 2)));
  ma = max(ma, base - naive(V<P>(begin(v) + 1, end(v) - 1)));
  ma = max(ma, base - naive(V<P>(begin(v) + 2, end(v))));

  ma = max(ma, base - naive(V<P>(begin(v), end(v) - 1)) +
                   solve(V<P>(begin(v), end(v) - 1), true));
  ma = max(ma, base - naive(V<P>(begin(v) + 1, end(v))) +
                   solve(V<P>(begin(v) + 1, end(v)), true));

  ma = max(ma, solve(v));
  cout << ma << endl;

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

using D = double;
const D PI = acos(D(-1)), EPS = 1e-10;

struct Pt2 {
  D x, y;
  Pt2() {}
  Pt2(D _x, D _y) : x(_x), y(_y) {}
  Pt2 operator+(const Pt2 &r) const { return Pt2(x + r.x, y + r.y); }
  Pt2 operator-(const Pt2 &r) const { return Pt2(x - r.x, y - r.y); }
  Pt2 operator*(const Pt2 &r) const {
    return Pt2(x * r.x - y * r.y, x * r.y + y * r.x);
  }
  Pt2 &operator+=(const Pt2 &r) { return *this = *this + r; }
  Pt2 &operator-=(const Pt2 &r) { return *this = *this - r; }
  Pt2 &operator*=(const Pt2 &r) { return *this = *this * r; }

  Pt2 operator-() const { return Pt2(-x, -y); }

  D abs() const { return sqrt(x * x + y * y); }
  D rabs() const { return max(x, y); } // robust abs
  D arg() const { return atan2(y, x); }

  pair<D, D> to_pair() const { return make_pair(x, y); }
  static Pt2 polar(D le, D th) { return Pt2(le * cos(th), le * sin(th)); }
};
template <class T> ostream &operator<<(ostream &os, const Pt2 &p) {
  os << "(" << p.x << ", " << p.y << ")";
  return os;
}
using P = Pt2;

int sgn(D a) {
  if (abs(a) <= EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
// relative sign
int rsgn(D a, D f) {
  if (abs(a) <= f * EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
bool near(P a, P b) { return !sgn((a - b).abs()); }

bool lessP(P l, P r) {
  if (sgn(r.x - l.x))
    return l.x < r.x;
  if (sgn(r.y - l.y))
    return l.y < r.y;
  return false;
}

D cross(P a, P b) { return a.x * b.y - a.y * b.x; }
D dot(P a, P b) { return a.x * b.x + a.y * b.y; }

// -2, -1, 0, 1, 2 : front, clock, on, cclock, back
int ccw(P b, P c) {
  int s = rsgn(cross(b, c), b.rabs());
  if (s)
    return s;
  if (!sgn(c.rabs()) || !sgn((c - b).rabs()))
    return 0;
  if (dot(b, c) < 0)
    return 2;
  if (dot(-b, c - b) < 0)
    return -2;
  return 0;
}
int ccw(P a, P b, P c) { return ccw(b - a, c - a); }

using Pol = V<P>;

Pol convex_up(const Pol &p, int l, int r, int e1 = -1, int e2 = -1) {
  Pol up;
  for (int i = l; i <= r; i++) {
    if (i == e1 || i == e2)
      continue;
    P d = p[i];
    while (up.size() > 1 && ccw(up[up.size() - 2], up[up.size() - 1], d) == 1)
      up.pop_back();
    up.push_back(d);
  }
  return up;
}

Pol convex_down(const Pol &p, int l, int r, int e1 = -1, int e2 = -1) {
  Pol down;
  for (int i = l; i <= r; i++) {
    if (i == e1 || i == e2)
      continue;
    P d = p[i];
    while (down.size() > 1 &&
           ccw(down[down.size() - 2], down[down.size() - 1], d) == -1)
      down.pop_back();
    down.push_back(d);
  }
  return down;
}

D line_len(const Pol &p) {
  int n = int(p.size());
  D sm = 0;
  for (int i = 0; i < n - 1; i++) {
    sm += (p[i + 1] - p[i]).abs();
  }
  return sm;
}

bool operator<(const P &x, const P &y) { return lessP(x, y); }

D solve(V<P> v, bool one = false) {
  int n = int(v.size());
  map<P, int> mp;
  for (int i = 0; i < n; i++)
    mp[v[i]] = i;

  auto up = convex_up(v, 0, n - 1);
  auto down = convex_down(v, 0, n - 1);

  int un = int(up.size()), dn = int(down.size());
  V<D> bufu, bufd;
  for (int i = 1; i < un - 1; i++) {
    D base = (up[i - 1] - up[i]).abs() + (up[i] - up[i + 1]).abs();
    bufu.push_back(
        base - line_len(convex_up(v, mp[up[i - 1]], mp[up[i + 1]], mp[up[i]])));
  }

  for (int i = 1; i < dn - 1; i++) {
    D base = (down[i - 1] - down[i]).abs() + (down[i] - down[i + 1]).abs();
    bufd.push_back(base - line_len(convex_down(v, mp[down[i - 1]],
                                               mp[down[i + 1]], mp[down[i]])));
  }

  D ans = -1e100;
  D uma = -1e100, dma = -1e100;
  for (int i = 1; i < un - 2; i++) {
    ans = max(ans, uma + bufu[i]);
    uma = max(uma, bufu[i - 1]);
  }
  for (int i = 1; i < dn - 2; i++) {
    ans = max(ans, dma + bufd[i]);
    dma = max(dma, bufd[i - 1]);
  }
  for (auto d : bufu)
    uma = max(uma, d);
  for (auto d : bufd)
    dma = max(dma, d);

  if (one)
    return max(uma, dma);

  ans = max(ans, uma + dma);

  for (int i = 1; i < un - 1; i++) {
    D base = (up[i - 1] - up[i]).abs() + (up[i] - up[i + 1]).abs();
    auto npo = convex_up(v, mp[up[i - 1]], mp[up[i + 1]], mp[up[i]]);
    base -= line_len(npo);
    int m = int(npo.size());
    for (int j = 1; j < m - 1; j++) {
      D base2 = (npo[j - 1] - npo[j]).abs() + (npo[j] - npo[j + 1]).abs();
      ans = max(ans, base + base2 -
                         line_len(convex_up(v, mp[npo[j - 1]], mp[npo[j + 1]],
                                            mp[npo[j]], mp[up[i]])));
    }
  }

  for (int i = 1; i < dn - 1; i++) {
    D base = (down[i - 1] - down[i]).abs() + (down[i] - down[i + 1]).abs();
    auto npo = convex_down(v, mp[down[i - 1]], mp[down[i + 1]], mp[down[i]]);
    base -= line_len(npo);
    int m = int(npo.size());
    for (int j = 1; j < m - 1; j++) {
      D base2 = (npo[j - 1] - npo[j]).abs() + (npo[j] - npo[j + 1]).abs();
      ans = max(ans, base + base2 -
                         line_len(convex_down(v, mp[npo[j - 1]], mp[npo[j + 1]],
                                              mp[npo[j]], mp[down[i]])));
    }
  }

  for (int i = 1; i < un - 2; i++) {
    D base = (up[i - 1] - up[i]).abs() + (up[i] - up[i + 1]).abs() +
             (up[i + 1] - up[i + 2]).abs();
    ans = max(ans, base - line_len(convex_up(v, mp[up[i - 1]], mp[up[i + 2]],
                                             mp[up[i]], mp[up[i + 1]])));
  }
  for (int i = 1; i < dn - 2; i++) {
    D base = (down[i - 1] - down[i]).abs() + (down[i] - down[i + 1]).abs() +
             (down[i + 1] - down[i + 2]).abs();
    ans = max(ans,
              base - line_len(convex_down(v, mp[down[i - 1]], mp[down[i + 2]],
                                          mp[down[i]], mp[down[i + 1]])));
  }

  return ans;
}

D naive(V<P> v) {
  int n = int(v.size());
  auto up = convex_up(v, 0, n - 1);
  auto down = convex_down(v, 0, n - 1);

  return line_len(up) + line_len(down);
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);

  int n;
  cin >> n;
  V<P> v(n);
  for (int i = 0; i < n; i++) {
    D x, y;
    cin >> x >> y;
    v[i] = P(x, y);
    v[i] *= P::polar(1, 13.4514);
  }
  sort(begin(v), end(v));

  D ma = -1;
  D base = naive(v);
  ma = max(ma, base - naive(V<P>(begin(v), end(v) - 2)));
  ma = max(ma, base - naive(V<P>(begin(v) + 1, end(v) - 1)));
  ma = max(ma, base - naive(V<P>(begin(v) + 2, end(v))));

  ma = max(ma, base - naive(V<P>(begin(v), end(v) - 1)) +
                   solve(V<P>(begin(v), end(v) - 1), true));
  ma = max(ma, base - naive(V<P>(begin(v) + 1, end(v))) +
                   solve(V<P>(begin(v) + 1, end(v)), true));

  ma = max(ma, solve(v));
  cout << ma << endl;

  return 0;
}