#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

constexpr double EPS = 1e-10;

struct Point {
  double x, y;
  constexpr Point () : x(0.), y(0.) {}
  template <typename T, typename U> constexpr Point (const T& _x, const U& _y) : x(_x), y(_y) {}
  constexpr Point (const Point& p) : x(p.x), y(p.y) {}
  template <typename T> constexpr Point (const pair<T, T>& p) : x(static_cast<double>(p.first)), y(static_cast<double>(p.second)) {}

  constexpr Point& operator= (const Point& other) & noexcept { this->x = other.x; this->y = other.y; return *this; }
  template <typename T> constexpr Point& operator= (const pair<T, T>& other) & noexcept { return *this = Point(other); }

  constexpr Point& operator+= (const Point& other) noexcept { this->x += other.x; this->y += other.y; return *this; }
  template <typename T> constexpr Point& operator+= (const pair<T, T>& other) noexcept { return *this += Point(other); }

  constexpr Point& operator-= (const Point& other) noexcept { this->x -= other.x; this->y -= other.y; return *this; }
  template <typename T> constexpr Point& operator-= (const pair<T, T>& other) noexcept { return *this -= Point(other); }

  template <typename T> Point& operator*= (const T& other) noexcept {double val = static_cast<double>(other); this->x *= val; this->y *= val; return *this; }
  
  template <typename T> Point& operator/= (const T& other) noexcept {double val = static_cast<double>(other); this->x /= val; this->y /= val; return *this; }

  friend constexpr bool operator== (const Point& lhs, const Point& rhs) noexcept {return lhs.x == rhs.x && lhs.y == rhs.y; }
  template <typename T> friend constexpr bool operator== (const Point& lhs, const pair<T, T>& rhs) noexcept {return lhs.x == rhs.first && lhs.y == rhs.second; }
  template <typename T> friend constexpr bool operator== (const pair<T, T>& lhs, const Point& rhs) noexcept {return lhs.first == rhs.x && lhs.second == rhs.y; }

  friend constexpr bool operator!= (const Point& lhs, const Point& rhs) noexcept {return !(lhs == rhs); }
  template <typename T> friend constexpr bool operator!= (const Point& lhs, const pair<T, T>& rhs) noexcept {return !(lhs == rhs); }
  template <typename T> friend constexpr bool operator!= (const pair<T, T>& lhs, const Point& rhs) noexcept {return !(lhs == rhs); }

  friend constexpr bool operator< (const Point& lhs, const Point& rhs) noexcept {return (abs(lhs.x - rhs.x) > EPS ? lhs.x < rhs.x : lhs.y < rhs.y); }
  template <typename T> friend constexpr bool operator< (const Point& lhs, const pair<T, T>& rhs) noexcept {return lhs < Point(rhs); }
  template <typename T> friend constexpr bool operator< (const pair<T, T>& lhs, const Point& rhs) noexcept {return Point(lhs) < rhs; }

  friend constexpr bool operator> (const Point& lhs, const Point& rhs) noexcept {return (abs(lhs.x - rhs.x) > EPS ? lhs.x > rhs.x : lhs.y > rhs.y); }
  template <typename T> friend constexpr bool operator> (const Point& lhs, const pair<T, T>& rhs) noexcept {return lhs > Point(rhs); }
  template <typename T> friend constexpr bool operator> (const pair<T, T>& lhs, const Point& rhs) noexcept {return Point(lhs) > rhs; }

  friend constexpr bool operator<= (const Point& lhs, const Point& rhs) noexcept {return !(lhs > rhs); }
  template <typename T> friend constexpr bool operator<= (const Point& lhs, const pair<T, T>& rhs) noexcept {return !(lhs > Point(rhs)); }
  template <typename T> friend constexpr bool operator<= (const pair<T, T>& lhs, const Point& rhs) noexcept {return !(Point(lhs) > rhs); }

  friend constexpr bool operator>= (const Point& lhs, const Point& rhs) noexcept {return !(lhs < rhs); }
  template <typename T> friend constexpr bool operator>= (const Point& lhs, const pair<T, T>& rhs) noexcept {return !(lhs < Point(rhs)); }
  template <typename T> friend constexpr bool operator>= (const pair<T, T>& lhs, const Point& rhs) noexcept {return !(Point(lhs) < rhs); }

  friend constexpr Point operator+ (const Point& lhs, const Point& rhs) noexcept { return Point(lhs) += rhs; }
  template <typename T> friend constexpr Point operator+ (const Point& lhs, const pair<T, T>& rhs) noexcept { return Point(lhs) += rhs; }
  template <typename T> friend constexpr Point operator+ (const pair<T, T>& lhs, const Point& rhs) noexcept { return Point(lhs) += rhs; }

  friend constexpr Point operator- (const Point& lhs, const Point& rhs) noexcept { return Point(lhs) -= rhs; }
  template <typename T> friend constexpr Point operator- (const Point& lhs, const pair<T, T>& rhs) noexcept { return Point(lhs) -= rhs; }
  template <typename T> friend constexpr Point operator- (const pair<T, T>& lhs, const Point& rhs) noexcept { return Point(lhs) -= rhs; }

  template<typename T> friend constexpr Point operator* (const Point& lhs, const T& rhs) noexcept { return Point(lhs) *= rhs; }
  template<typename T> friend constexpr Point operator* (const T& lhs, const Point& rhs) noexcept { return Point(rhs) *= lhs; }

  template<typename T> friend constexpr Point operator/ (const Point& lhs, const T& rhs) noexcept { return Point(lhs) /= rhs; }
  template<typename T> friend constexpr Point operator/ (const T& lhs, const Point& rhs) noexcept { return Point(rhs) /= lhs; }

  friend ostream& operator << (ostream& s, const Point& p) { return s << p.x << " " << p.y; }
};

constexpr Point conj (const Point& p) {return Point(p.x, -p.y); }
// The angle is in radian
template <typename T> constexpr Point rot (const Point& p, const T& angle) { return Point(cos(angle) * p.x - sin(angle) * p.y, sin(angle) * p.x + cos(angle) * p.y); }
constexpr double cross (const Point& p, const Point& q) { return p.x * q.y - p.y * q.x; }
constexpr double dot (const Point& p, const Point& q) { return p.x * q.x + p.y * q.y; }
constexpr double norm (const Point& p) { return dot(p, p); }
constexpr double abs (const Point& p ) { return sqrt(dot(p, p)); }
constexpr double amp (const Point& p ) { double res = atan2(p.y, p.x); if (res < 0) res += M_PI * 2; return res; }


vector<Point> ConvexHull (vector<Point>& points, bool sortByAngle = false, bool includeMiddlePoint = false) {
  int n = (int) points.size();
  sort(points.begin(), points.end());
  if (sortByAngle) {
    auto compByAngle = [&] (const Point& p, const Point& q) {
      Point a = p - points[0];
      Point b = q - points[0];
      double e = a.y * b.x - a.x * b.y;
      return abs(e) < EPS ? norm(a) < norm(b) : e < 0;
    };
    sort(points.begin() + 1, points.end(), compByAngle);
  }
  int itr = 0;
  vector<Point> res(n * 2);
  for (int i = 0; i < n; ++i) {
    if (itr >= 2) {
      while (cross(res[itr- 1] - res[itr - 2], points[i] - res[itr - 2]) < (includeMiddlePoint ? -EPS : EPS)) {
        --itr;
        if (itr < 2) break;
      }
    }
    res[itr++] = points[i];
  }
  int bound = itr + 1;
  for (int i = n - 2; i >= 0; i--) {
    if (itr >= bound) {
      while (cross(res[itr- 1] - res[itr - 2], points[i] - res[itr - 2]) < (includeMiddlePoint ? -EPS : EPS)) {
        --itr;
        if (itr < bound) break;
      }
    }
    res[itr++] = points[i];
  }
  res.resize(itr - 1);
  return res;
}

void AOJ_CGL_4_L() {
  int n;
  cin >> n;
  vector<Point> points(n);
  for (int i = 0; i < n; i++) {
    cin >> points[i].x >> points[i].y;
  }
  auto res = ConvexHull(points, true, true);
  Point mx(1e9, 1e9);
  int idx = 0;
  for (int i = 0; i < (int) res.size(); i++) {
    if (mx.y > res[i].y) {
      mx = res[i];
      idx = i;
    } else if (abs(mx.y - res[i].y) < EPS && res[i].x < mx.x) {
      mx = res[i];
      idx = i;
    }
  }
  int m = res.size();
  cout << m << '\n';
  for (int i = 0; i < m; i++) {
    cout << res[(idx + i) % m].x << " " << res[(idx + i) % m].y << '\n';
  }
}

signed main() { 
  ios::sync_with_stdio(false); cin.tie(0);
  AOJ_CGL_4_L();
  return 0;
}


Measured memory_bytes: 7560