Problem p01747 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using V = complex<ld>;
using L = pair<V, V>;
constexpr ld PI = static_cast<ld>(3.1415926535898);
constexpr ld EPS = static_cast<ld>(1e-12);

// 点をsetとかmapにつめたいとき(誤差を1e-10とか厳しくし過ぎるとバグる)
// inline bool operator<(const C a, const C b){
//     return abs(a.real()-b.real())>EPS ? a.real()<b.real()-EPS :
//     a.imag()<b.imag()-EPS;
// }

namespace std {
inline bool equal(const ld a, const ld b) {
  return (-EPS < a - b and a - b < EPS);
}

inline bool operator<(const V &a, const V &b) {
  return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
}

inline bool operator==(const V &c1, const V &c2) {
  return (equal(c1.real(), c2.real()) and equal(c1.imag(), c2.imag()));
}

inline bool operator!=(const V &a, const V &b) { return !(a == b); }
} // namespace std

inline ld Sqrt(const ld x) { return (x < 0 ? 0 : sqrt(x)); }

inline V normalize(const V &c) { return c / abs(c); }

inline ld arg(const V &a, const V &b) { return arg(b * conj(a)); }

inline ld cross(const V &a, const V &b) { return imag(conj(a) * b); }

inline ld dot(const V &a, const V &b) { return real(conj(a) * b); }

inline int ccw(const V &a, const V &b, const V &c) {
  if (cross(b - a, c - a) > 0) {
    return +1; // counter clockwise
  }
  if (cross(b - a, c - a) < 0) {
    return -1; // clockwise
  }
  if (dot(b - a, c - a) < 0) {
    return +2; // c--a--b on line
  }
  if (norm(b - a) < norm(c - a)) {
    return -2; // a--b--c on line
  }
  return 0; // b--a--c on line
}

inline bool intersectLL(const L &l, const L &m) {
  return abs(cross(l.second - l.first, m.second - m.first)) > EPS or
         abs(cross(l.second - l.first, m.first - l.first)) < EPS;
}

inline bool intersectLS(const L &l, const L &s) {
  return cross(l.second - l.first, s.first - l.first) *
             cross(l.second - l.first, s.second - l.first) <
         EPS;
}

inline bool intersectLP(const L &l, const V &p) {
  return abs(cross(l.second - p, l.first - p)) < EPS;
}

inline bool intersectSS(const L &s, const L &t) {
  return ccw(s.first, s.second, t.first) * ccw(s.first, s.second, t.second) <=
             0 and
         ccw(t.first, t.second, s.first) * ccw(t.first, t.second, s.second) <=
             0;
}

inline bool intersectSP(const L &s, const V &p) {
  return abs(s.first - p) + abs(s.second - p) - abs(s.second - s.first) < EPS;
}

inline V crosspointLL(const L &l, const L &m) {
  const ld A = cross(l.second - l.first, m.second - m.first);
  const ld B = cross(l.second - l.first, l.second - m.first);
  // 同一直線のとき
  if (abs(A) < EPS and abs(B) < EPS) {
    return m.first;
  }
  return m.first + (B / A) * (m.second - m.first);
}

// 点pを直線l上に射影
inline V projection(const L &l, const V &p) {
  const ld t = dot(p - l.first, l.first - l.second) / norm(l.first - l.second);
  return l.first + t * (l.first - l.second);
}

// crosspointCLに使用する関数(命名が謎です)
inline ld gettime(const V &c1, const V &c2) {
  return (dot(c1, c2) < 0 ? -1.0 : 1.0) * abs(c2) / abs(c1);
}

// 円と直線の交点
inline vector<V> crosspointCL(const V &c1, const ld r1, const L &l) {
  const V a = l.first;
  const V b = l.second;
  vector<V> res;
  const V target = projection(L(a, b), c1);
  const V base = normalize(b - a);
  const ld h = abs(c1 - target);
  if (r1 + EPS < h) {
    return res;
  }
  const ld w = Sqrt(r1 * r1 - h * h);
  const ld LL = gettime(normalize(b - a), target - a) - w;
  const ld RR = LL + w * 2.0;
  res.push_back(a + base * LL);
  if (equal(LL, RR)) {
    return res;
  }
  res.push_back(a + base * RR);
  return res;
}

// 円と線分の交点
inline vector<V> crosspointCS(const V &c1, const ld r1, const L &s) {
  vector<V> tmp = crosspointCL(c1, r1, s);
  vector<V> res;
  for (int i = 0; i < tmp.size(); i++) {
    if (abs(s.second - s.first) ==
        abs(s.first - tmp[i]) + abs(s.second - tmp[i])) {
      res.push_back(tmp[i]);
    }
  }
  return res;
}

// 円どうしの交点
inline L crosspointCC(const V &c1, const ld r1, const V &c2, const ld r2) {
  const V a = conj(c2 - c1);
  const V b = (r2 * r2 - r1 * r1 - (c2 - c1) * conj(c2 - c1));
  const V c = r1 * r1 * (c2 - c1);
  const V d = b * b - (ld)4.0 * a * c;
  const V z1 = (-b + sqrt(d)) / ((ld)2.0 * a) + c1;
  const V z2 = (-b - sqrt(d)) / ((ld)2.0 * a) + c1;
  return L(z1, z2);
}

// 点pを直線lを軸として対称移動
inline V reflection(const L &l, const V &p) {
  return p + (projection(l, p) - p) * (ld)2.0;
}

// 点と直線の距離
inline ld distanceLP(const L &l, const V &p) {
  return abs(p - projection(l, p));
}

// 直線と直線の距離
inline ld distanceLL(const L &l, const L &m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.first);
}

// 直線と線分の距離
inline ld distanceLS(const L &l, const L &s) {
  if (intersectLS(l, s)) {
    return 0;
  }
  return min(distanceLP(l, s.first), distanceLP(l, s.second));
}
// 線分と点の距離
inline ld distanceSP(const L &s, const V &p) {
  const V r = projection(s, p);
  if (intersectSP(s, r)) {
    return abs(r - p);
  }
  return min(abs(s.first - p), abs(s.second - p));
}

// 線分と線分の距離
inline ld distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) {
    return 0;
  }
  return min(min(distanceSP(s, t.first), distanceSP(s, t.second)),
             min(distanceSP(t, s.first), distanceSP(t, s.second)));
}

inline ld getarea(const V &c1, const ld r1, const V &a, const V &b) {
  const V va = c1 - a;
  const V vb = c1 - b;
  const ld A = abs(va);
  const ld B = abs(vb);
  const ld f = cross(va, vb);
  const ld d = distanceSP(L(a, b), c1);
  ld res = 0;
  if (equal(f, (ld)0.0)) {
    return 0;
  }
  if (A < r1 + EPS and B < r1 + EPS) {
    return f * (ld)0.5;
  }
  if (d > r1 - EPS) {
    return r1 * r1 * M_PI * arg(va, vb) / ((ld)2.0 * M_PI);
  }
  vector<V> u = crosspointCS(c1, r1, L(a, b));
  u.insert(u.begin(), a);
  u.push_back(b);
  for (int i = 0; i + 1 < (int)u.size(); i++) {
    res += getarea(c1, r1, u[i], u[i + 1]);
  }
  return res;
}

// 円と多角形の共通部分の面積
inline ld getcrossarea(const vector<V> &t, const V &c1, const ld r1) {
  const int n = t.size();
  if (n < 3) {
    return 0;
  }
  ld res = 0;
  for (int i = 0; i < n; i++) {
    const V a = t[i];
    const V b = t[(i + 1) % n];
    res += getarea(c1, r1, a, b);
  }
  return res;
}

// 凸包を求める(O(nlogn))
inline vector<V> convex_hull(vector<V> ps) {
  const int n = (int)ps.size();
  int k = 0;
  sort(ps.begin(), ps.end());
  vector<V> ch(2 * n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) {
    while (k >= 2 and ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) {
      k--;
    }
  }
  for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) {
    while (k >= t and ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) {
      k--;
    }
  }
  ch.resize(k - 1);
  return ch;
}

// 凸性判定
inline bool isconvex(const vector<V> &ps) {
  for (int i = 0; i < ps.size(); i++) {
    if (ccw(ps[(i + ps.size() - 1) % ps.size()], ps[i],
            ps[(i + 1) % ps.size()])) {
      return false;
    }
  }
  return true;
}

// 多角形の符号付き面積(左回りが正)
inline ld area(const vector<V> &ps) {
  ld A = 0;
  for (int i = 0; i < ps.size(); i++) {
    A += cross(ps[i], ps[(i + 1) % ps.size()]);
  }
  return A / (ld)2.0;
}

// 凸多角形を直線で切断した時の左側の図形
vector<V> convex_cut(const vector<V> &ps, const L &l) {
  vector<V> Q;
  for (int i = 0; i < ps.size(); i++) {
    const V A = ps[i];
    const V B = ps[(i + 1) % ps.size()];
    if (ccw(l.first, l.second, A) != -1) {
      Q.push_back(A);
    }
    if (ccw(l.first, l.second, A) * ccw(l.first, l.second, B) < 0) {
      Q.push_back(crosspointLL(L(A, B), l));
    }
  }
  return Q;
}

// 点が多角形に包含されているか(0は含まれない,1は辺上,2は含まれる)
int contains(const vector<V> &ps, const V &p) {
  bool flag = false;
  for (int i = 0; i < ps.size(); i++) {
    V a = ps[i] - p;
    V b = ps[(i + 1) % ps.size()] - p;
    if (imag(a) > imag(b)) {
      swap(a, b);
    }
    if (imag(a) <= 0 and 0 < imag(b)) {
      if (cross(a, b) < 0) {
        flag = not flag;
      }
    }
    if (cross(a, b) == 0 and dot(a, b) <= 0)
      return 1;
  }
  return flag ? 2 : 0;
}

// 凸多角形の交差
vector<V> convex_intersection(const vector<V> &ps, const vector<V> &qs) {
  vector<V> rs;
  const int a = ps.size();
  const int b = qs.size();
  for (int i = 0; i < a; i++) {
    if (contains(qs, ps[i])) {
      rs.push_back(ps[i]);
    }
  }
  for (int i = 0; i < b; i++) {
    if (contains(ps, qs[i])) {
      rs.push_back(qs[i]);
    }
  }
  for (int i = 0; i < a; i++) {
    for (int j = 0; j < b; j++) {
      const L l1(ps[i], ps[(i + 1) % a]);
      const L l2(qs[j], qs[(j + 1) % b]);
      if (intersectSS(l1, l2)) {
        rs.push_back(crosspointLL(l1, l2));
      }
    }
  }
  sort(rs.begin(), rs.end());
  rs.erase(unique(rs.begin(), rs.end()), rs.end());
  if (rs.size() <= 1) {
    return rs;
  }
  return convex_hull(rs);
}

// 凸多角形の直径を求める(キャリパー法)
// maxi,maxjが最遠点対となる
inline ld convex_diameter(const vector<V> &ps) {
  const int n = ps.size();
  int is = 0;
  int js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(ps[i]) > imag(ps[is])) {
      is = i;
    }
    if (imag(ps[i]) < imag(ps[js])) {
      js = i;
    }
  }
  ld maxd = abs(ps[is] - ps[js]);
  int i;
  int maxi;
  int j;
  int maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(ps[(i + 1) % ps.size()] - ps[i],
              ps[(j + 1) % ps.size()] - ps[j]) >= 0)
      j = (j + 1) % n;
    else
      i = (i + 1) % n;
    if (abs(ps[i] - ps[j]) > maxd) {
      maxd = abs(ps[i] - ps[j]);
      maxi = i;
      maxj = j;
    }
  } while (i != is or j != js);
  return maxd;
}

inline bool compyx(const V &c1, const V &c2) {
  return c1.imag() != c2.imag() ? c1.imag() < c2.imag() : c1.real() < c2.real();
}

inline ld closest_pair(const vector<V>::iterator a, const int n) {
  if (n <= 1) {
    return 1e100;
  }
  int m = n / 2;
  ld x = a[m].real();
  ld d = min(closest_pair(a, m), closest_pair(a + m, n - m));
  inplace_merge(a, a + m, a + n, compyx);
  vector<V> b;
  for (int i = 0; i < n; i++) {
    if (abs(x - a[i].real()) >= d) {
      continue;
    }
    for (int j = 0; j < b.size(); j++) {
      V dp = a[i] - b[b.size() - 1 - j];
      if (dp.imag() >= d) {
        break;
      }
      d = min(d, abs(dp));
    }
    b.push_back(a[i]);
  }
  return d;
}

// 最近点対を求める
inline ld compute_shortest(const vector<V>::iterator a, const int n) {
  sort(a, a + n);
  return closest_pair(a, n);
}

// 2円の位置関係を示す(返り値は2円の間の共通接線の数)
inline int getstateCC(const V &c1, const ld r1, const V &c2, const ld r2) {
  ld d = abs(c1 - c2);
  if (d > r1 + r2 + EPS) {
    return 4;
  }
  if (d > r1 + r2 - EPS) {
    return 3;
  }
  if (d > abs(r1 - r2) + EPS) {
    return 2;
  }
  if (d > abs(r1 - r2) - EPS) {
    return 1;
  }
  return 0;
}

// 点から円へ接線を引いた時の接点
inline V gettangentCP_(const V &c1, const ld r1, const V &p, const int flg) {
  const V base = c1 - p;
  const ld w = Sqrt(norm(base) - r1 * r1);
  const V s = p + base * V(w, r1 * flg) / norm(base) * w;
  return s;
}

// 点から円への接線
inline vector<L> gettangentCP(const V &c1, const ld r1, const V &p) {
  vector<L> res;
  const V s = gettangentCP_(c1, r1, p, 1);
  const V t = gettangentCP_(c1, r1, p, -1);
  // 点が円の周上にある場合
  if (s == t) {
    res.push_back(L(s, s + (c1 - p) * V(0, 1)));
  } else {
    res.push_back(L(p, s));
    res.push_back(L(p, t));
  }
  return res;
}

// 2円の共通内接線を求める
inline L getintangent(const V &c1, const ld r1, const V &c2, const ld r2,
                      const ld flg) {
  const V base = c2 - c1;
  const ld w = r1 + r2;
  const ld h = Sqrt(norm(base) - w * w);
  const V k = base * V(w, h * flg) / norm(base);
  return L(c1 + k * r1, c2 - k * r2);
}

// 2円の共通外接線を求める
inline L getouttangent(const V &c1, const ld r1, const V &c2, const ld r2,
                       const ld flg) {
  const V base = c2 - c1;
  const ld h = r2 - r1;
  const ld w = Sqrt(norm(base) - h * h);
  const V k = base * V(w, h * flg) / norm(base) * V(0, flg);
  return L(c1 + k * r1, c2 + k * r2);
}

// 2円の共通接線を求める(各直線の２点はそれぞれの円の接点)
inline vector<L> gettangentCC(const V &c1, const ld r1, const V &c2,
                              const ld r2) {
  vector<L> res;
  const ld d = abs(c1 - c2);
  if (d > r1 + r2 + EPS) {
    res.push_back(getintangent(c1, r1, c2, r2, 1));
  }
  if (d > r1 + r2 - EPS) {
    res.push_back(getintangent(c1, r1, c2, r2, -1));
  }
  if (d > abs(r1 - r2) + EPS) {
    res.push_back(getouttangent(c1, r1, c2, r2, 1));
  }
  if (d > abs(r1 - r2) - EPS) {
    res.push_back(getouttangent(c1, r1, c2, r2, -1));
  }
  return res;
}

int main() {
  int N;
  cin >> N;
  vector<V> v(N);
  vector<vector<V>> cv(N);
  for (int i = 0; i < N; i++) {
    ld x, y;
    cin >> x >> y;
    v[i] = {x, y};
  }
  for (int i = 0; i < N; i++) {
    cv[i] = convex_hull(vector<V>(v.begin(), v.begin() + i + 1));
  }
  for (int i = 1; i < N; i++) {
    if (contains(cv[i - 1], v[i]) == 2) {
      cout << "Impossible" << endl;
      return 0;
    }
  }
  reverse(v.begin(), v.end());
  for (int i = 0; i < N; i++) {
    cv[i] = convex_hull(vector<V>(v.begin(), v.begin() + i + 1));
  }
  for (int i = 1; i < N; i++) {
    if (contains(cv[i - 1], v[i]) == 2) {
      cout << "Impossible" << endl;
      return 0;
    }
  }
  cout << "Possible" << endl;
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using V = complex<ld>;
using L = pair<V, V>;
constexpr ld PI = static_cast<ld>(3.1415926535898);
constexpr ld EPS = static_cast<ld>(1e-12);

// 点をsetとかmapにつめたいとき(誤差を1e-10とか厳しくし過ぎるとバグる)
// inline bool operator<(const C a, const C b){
//     return abs(a.real()-b.real())>EPS ? a.real()<b.real()-EPS :
//     a.imag()<b.imag()-EPS;
// }

namespace std {
inline bool equal(const ld a, const ld b) {
  return (-EPS < a - b and a - b < EPS);
}

inline bool operator<(const V &a, const V &b) {
  return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
}

inline bool operator==(const V &c1, const V &c2) {
  return (equal(c1.real(), c2.real()) and equal(c1.imag(), c2.imag()));
}

inline bool operator!=(const V &a, const V &b) { return !(a == b); }
} // namespace std

inline ld Sqrt(const ld x) { return (x < 0 ? 0 : sqrt(x)); }

inline V normalize(const V &c) { return c / abs(c); }

inline ld arg(const V &a, const V &b) { return arg(b * conj(a)); }

inline ld cross(const V &a, const V &b) { return imag(conj(a) * b); }

inline ld dot(const V &a, const V &b) { return real(conj(a) * b); }

inline int ccw(const V &a, const V &b, const V &c) {
  if (cross(b - a, c - a) > 0) {
    return +1; // counter clockwise
  }
  if (cross(b - a, c - a) < 0) {
    return -1; // clockwise
  }
  if (dot(b - a, c - a) < 0) {
    return +2; // c--a--b on line
  }
  if (norm(b - a) < norm(c - a)) {
    return -2; // a--b--c on line
  }
  return 0; // b--a--c on line
}

inline bool intersectLL(const L &l, const L &m) {
  return abs(cross(l.second - l.first, m.second - m.first)) > EPS or
         abs(cross(l.second - l.first, m.first - l.first)) < EPS;
}

inline bool intersectLS(const L &l, const L &s) {
  return cross(l.second - l.first, s.first - l.first) *
             cross(l.second - l.first, s.second - l.first) <
         EPS;
}

inline bool intersectLP(const L &l, const V &p) {
  return abs(cross(l.second - p, l.first - p)) < EPS;
}

inline bool intersectSS(const L &s, const L &t) {
  return ccw(s.first, s.second, t.first) * ccw(s.first, s.second, t.second) <=
             0 and
         ccw(t.first, t.second, s.first) * ccw(t.first, t.second, s.second) <=
             0;
}

inline bool intersectSP(const L &s, const V &p) {
  return abs(s.first - p) + abs(s.second - p) - abs(s.second - s.first) < EPS;
}

inline V crosspointLL(const L &l, const L &m) {
  const ld A = cross(l.second - l.first, m.second - m.first);
  const ld B = cross(l.second - l.first, l.second - m.first);
  // 同一直線のとき
  if (abs(A) < EPS and abs(B) < EPS) {
    return m.first;
  }
  return m.first + (B / A) * (m.second - m.first);
}

// 点pを直線l上に射影
inline V projection(const L &l, const V &p) {
  const ld t = dot(p - l.first, l.first - l.second) / norm(l.first - l.second);
  return l.first + t * (l.first - l.second);
}

// crosspointCLに使用する関数(命名が謎です)
inline ld gettime(const V &c1, const V &c2) {
  return (dot(c1, c2) < 0 ? -1.0 : 1.0) * abs(c2) / abs(c1);
}

// 円と直線の交点
inline vector<V> crosspointCL(const V &c1, const ld r1, const L &l) {
  const V a = l.first;
  const V b = l.second;
  vector<V> res;
  const V target = projection(L(a, b), c1);
  const V base = normalize(b - a);
  const ld h = abs(c1 - target);
  if (r1 + EPS < h) {
    return res;
  }
  const ld w = Sqrt(r1 * r1 - h * h);
  const ld LL = gettime(normalize(b - a), target - a) - w;
  const ld RR = LL + w * 2.0;
  res.push_back(a + base * LL);
  if (equal(LL, RR)) {
    return res;
  }
  res.push_back(a + base * RR);
  return res;
}

// 円と線分の交点
inline vector<V> crosspointCS(const V &c1, const ld r1, const L &s) {
  vector<V> tmp = crosspointCL(c1, r1, s);
  vector<V> res;
  for (int i = 0; i < tmp.size(); i++) {
    if (abs(s.second - s.first) ==
        abs(s.first - tmp[i]) + abs(s.second - tmp[i])) {
      res.push_back(tmp[i]);
    }
  }
  return res;
}

// 円どうしの交点
inline L crosspointCC(const V &c1, const ld r1, const V &c2, const ld r2) {
  const V a = conj(c2 - c1);
  const V b = (r2 * r2 - r1 * r1 - (c2 - c1) * conj(c2 - c1));
  const V c = r1 * r1 * (c2 - c1);
  const V d = b * b - (ld)4.0 * a * c;
  const V z1 = (-b + sqrt(d)) / ((ld)2.0 * a) + c1;
  const V z2 = (-b - sqrt(d)) / ((ld)2.0 * a) + c1;
  return L(z1, z2);
}

// 点pを直線lを軸として対称移動
inline V reflection(const L &l, const V &p) {
  return p + (projection(l, p) - p) * (ld)2.0;
}

// 点と直線の距離
inline ld distanceLP(const L &l, const V &p) {
  return abs(p - projection(l, p));
}

// 直線と直線の距離
inline ld distanceLL(const L &l, const L &m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.first);
}

// 直線と線分の距離
inline ld distanceLS(const L &l, const L &s) {
  if (intersectLS(l, s)) {
    return 0;
  }
  return min(distanceLP(l, s.first), distanceLP(l, s.second));
}
// 線分と点の距離
inline ld distanceSP(const L &s, const V &p) {
  const V r = projection(s, p);
  if (intersectSP(s, r)) {
    return abs(r - p);
  }
  return min(abs(s.first - p), abs(s.second - p));
}

// 線分と線分の距離
inline ld distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) {
    return 0;
  }
  return min(min(distanceSP(s, t.first), distanceSP(s, t.second)),
             min(distanceSP(t, s.first), distanceSP(t, s.second)));
}

inline ld getarea(const V &c1, const ld r1, const V &a, const V &b) {
  const V va = c1 - a;
  const V vb = c1 - b;
  const ld A = abs(va);
  const ld B = abs(vb);
  const ld f = cross(va, vb);
  const ld d = distanceSP(L(a, b), c1);
  ld res = 0;
  if (equal(f, (ld)0.0)) {
    return 0;
  }
  if (A < r1 + EPS and B < r1 + EPS) {
    return f * (ld)0.5;
  }
  if (d > r1 - EPS) {
    return r1 * r1 * M_PI * arg(va, vb) / ((ld)2.0 * M_PI);
  }
  vector<V> u = crosspointCS(c1, r1, L(a, b));
  u.insert(u.begin(), a);
  u.push_back(b);
  for (int i = 0; i + 1 < (int)u.size(); i++) {
    res += getarea(c1, r1, u[i], u[i + 1]);
  }
  return res;
}

// 円と多角形の共通部分の面積
inline ld getcrossarea(const vector<V> &t, const V &c1, const ld r1) {
  const int n = t.size();
  if (n < 3) {
    return 0;
  }
  ld res = 0;
  for (int i = 0; i < n; i++) {
    const V a = t[i];
    const V b = t[(i + 1) % n];
    res += getarea(c1, r1, a, b);
  }
  return res;
}

// 凸包を求める(O(nlogn))
inline vector<V> convex_hull(vector<V> ps) {
  const int n = (int)ps.size();
  int k = 0;
  sort(ps.begin(), ps.end());
  vector<V> ch(2 * n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) {
    while (k >= 2 and ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) {
      k--;
    }
  }
  for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) {
    while (k >= t and ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) {
      k--;
    }
  }
  ch.resize(k - 1);
  return ch;
}

// 凸性判定
inline bool isconvex(const vector<V> &ps) {
  for (int i = 0; i < ps.size(); i++) {
    if (ccw(ps[(i + ps.size() - 1) % ps.size()], ps[i],
            ps[(i + 1) % ps.size()])) {
      return false;
    }
  }
  return true;
}

// 多角形の符号付き面積(左回りが正)
inline ld area(const vector<V> &ps) {
  ld A = 0;
  for (int i = 0; i < ps.size(); i++) {
    A += cross(ps[i], ps[(i + 1) % ps.size()]);
  }
  return A / (ld)2.0;
}

// 凸多角形を直線で切断した時の左側の図形
vector<V> convex_cut(const vector<V> &ps, const L &l) {
  vector<V> Q;
  for (int i = 0; i < ps.size(); i++) {
    const V A = ps[i];
    const V B = ps[(i + 1) % ps.size()];
    if (ccw(l.first, l.second, A) != -1) {
      Q.push_back(A);
    }
    if (ccw(l.first, l.second, A) * ccw(l.first, l.second, B) < 0) {
      Q.push_back(crosspointLL(L(A, B), l));
    }
  }
  return Q;
}

// 点が多角形に包含されているか(0は含まれない,1は辺上,2は含まれる)
int contains(const vector<V> &ps, const V &p) {
  bool flag = false;
  for (int i = 0; i < ps.size(); i++) {
    V a = ps[i] - p;
    V b = ps[(i + 1) % ps.size()] - p;
    if (imag(a) > imag(b)) {
      swap(a, b);
    }
    if (imag(a) <= 0 and 0 < imag(b)) {
      if (cross(a, b) < 0) {
        flag = not flag;
      }
    }
    if (cross(a, b) == 0 and dot(a, b) <= 0)
      return 1;
  }
  return flag ? 2 : 0;
}

// 凸多角形の交差
vector<V> convex_intersection(const vector<V> &ps, const vector<V> &qs) {
  vector<V> rs;
  const int a = ps.size();
  const int b = qs.size();
  for (int i = 0; i < a; i++) {
    if (contains(qs, ps[i])) {
      rs.push_back(ps[i]);
    }
  }
  for (int i = 0; i < b; i++) {
    if (contains(ps, qs[i])) {
      rs.push_back(qs[i]);
    }
  }
  for (int i = 0; i < a; i++) {
    for (int j = 0; j < b; j++) {
      const L l1(ps[i], ps[(i + 1) % a]);
      const L l2(qs[j], qs[(j + 1) % b]);
      if (intersectSS(l1, l2)) {
        rs.push_back(crosspointLL(l1, l2));
      }
    }
  }
  sort(rs.begin(), rs.end());
  rs.erase(unique(rs.begin(), rs.end()), rs.end());
  if (rs.size() <= 1) {
    return rs;
  }
  return convex_hull(rs);
}

// 凸多角形の直径を求める(キャリパー法)
// maxi,maxjが最遠点対となる
inline ld convex_diameter(const vector<V> &ps) {
  const int n = ps.size();
  int is = 0;
  int js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(ps[i]) > imag(ps[is])) {
      is = i;
    }
    if (imag(ps[i]) < imag(ps[js])) {
      js = i;
    }
  }
  ld maxd = abs(ps[is] - ps[js]);
  int i;
  int maxi;
  int j;
  int maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(ps[(i + 1) % ps.size()] - ps[i],
              ps[(j + 1) % ps.size()] - ps[j]) >= 0)
      j = (j + 1) % n;
    else
      i = (i + 1) % n;
    if (abs(ps[i] - ps[j]) > maxd) {
      maxd = abs(ps[i] - ps[j]);
      maxi = i;
      maxj = j;
    }
  } while (i != is or j != js);
  return maxd;
}

inline bool compyx(const V &c1, const V &c2) {
  return c1.imag() != c2.imag() ? c1.imag() < c2.imag() : c1.real() < c2.real();
}

inline ld closest_pair(const vector<V>::iterator a, const int n) {
  if (n <= 1) {
    return 1e100;
  }
  int m = n / 2;
  ld x = a[m].real();
  ld d = min(closest_pair(a, m), closest_pair(a + m, n - m));
  inplace_merge(a, a + m, a + n, compyx);
  vector<V> b;
  for (int i = 0; i < n; i++) {
    if (abs(x - a[i].real()) >= d) {
      continue;
    }
    for (int j = 0; j < b.size(); j++) {
      V dp = a[i] - b[b.size() - 1 - j];
      if (dp.imag() >= d) {
        break;
      }
      d = min(d, abs(dp));
    }
    b.push_back(a[i]);
  }
  return d;
}

// 最近点対を求める
inline ld compute_shortest(const vector<V>::iterator a, const int n) {
  sort(a, a + n);
  return closest_pair(a, n);
}

// 2円の位置関係を示す(返り値は2円の間の共通接線の数)
inline int getstateCC(const V &c1, const ld r1, const V &c2, const ld r2) {
  ld d = abs(c1 - c2);
  if (d > r1 + r2 + EPS) {
    return 4;
  }
  if (d > r1 + r2 - EPS) {
    return 3;
  }
  if (d > abs(r1 - r2) + EPS) {
    return 2;
  }
  if (d > abs(r1 - r2) - EPS) {
    return 1;
  }
  return 0;
}

// 点から円へ接線を引いた時の接点
inline V gettangentCP_(const V &c1, const ld r1, const V &p, const int flg) {
  const V base = c1 - p;
  const ld w = Sqrt(norm(base) - r1 * r1);
  const V s = p + base * V(w, r1 * flg) / norm(base) * w;
  return s;
}

// 点から円への接線
inline vector<L> gettangentCP(const V &c1, const ld r1, const V &p) {
  vector<L> res;
  const V s = gettangentCP_(c1, r1, p, 1);
  const V t = gettangentCP_(c1, r1, p, -1);
  // 点が円の周上にある場合
  if (s == t) {
    res.push_back(L(s, s + (c1 - p) * V(0, 1)));
  } else {
    res.push_back(L(p, s));
    res.push_back(L(p, t));
  }
  return res;
}

// 2円の共通内接線を求める
inline L getintangent(const V &c1, const ld r1, const V &c2, const ld r2,
                      const ld flg) {
  const V base = c2 - c1;
  const ld w = r1 + r2;
  const ld h = Sqrt(norm(base) - w * w);
  const V k = base * V(w, h * flg) / norm(base);
  return L(c1 + k * r1, c2 - k * r2);
}

// 2円の共通外接線を求める
inline L getouttangent(const V &c1, const ld r1, const V &c2, const ld r2,
                       const ld flg) {
  const V base = c2 - c1;
  const ld h = r2 - r1;
  const ld w = Sqrt(norm(base) - h * h);
  const V k = base * V(w, h * flg) / norm(base) * V(0, flg);
  return L(c1 + k * r1, c2 + k * r2);
}

// 2円の共通接線を求める(各直線の２点はそれぞれの円の接点)
inline vector<L> gettangentCC(const V &c1, const ld r1, const V &c2,
                              const ld r2) {
  vector<L> res;
  const ld d = abs(c1 - c2);
  if (d > r1 + r2 + EPS) {
    res.push_back(getintangent(c1, r1, c2, r2, 1));
  }
  if (d > r1 + r2 - EPS) {
    res.push_back(getintangent(c1, r1, c2, r2, -1));
  }
  if (d > abs(r1 - r2) + EPS) {
    res.push_back(getouttangent(c1, r1, c2, r2, 1));
  }
  if (d > abs(r1 - r2) - EPS) {
    res.push_back(getouttangent(c1, r1, c2, r2, -1));
  }
  return res;
}

int main() {
  int N;
  cin >> N;
  vector<V> v(N);
  vector<V> rev(N);
  vector<vector<V>> cv(N);
  vector<vector<V>> revcv(N);
  for (int i = 0; i < N; i++) {
    ld x, y;
    cin >> x >> y;
    v[i] = {x, y};
    rev[N - 1 - i] = {x, y};
  }
  for (int i = 0; i < N; i++) {
    cv[i] = convex_hull(vector<V>(v.begin(), v.begin() + i + 1));
    revcv[i] = convex_hull(vector<V>(rev.begin(), rev.begin() + i + 1));
  }
  for (int i = 0; i < N; i++) {
    if (convex_intersection(cv[i], revcv[N - i - 1]).size() >= 3) {
      cout << "Impossible" << endl;
      return 0;
    }
  }
  cout << "Possible" << endl;
  return 0;
}