#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <bitset>
#include <functional>
using namespace std;

#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,n) repl(i,0,n)
#define mp(a,b) make_pair((a),(b))
#define pb(a) push_back(a)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<(x)<<endl
#define fi first
#define se second

#define INF 2147483600
#define EPS 1e-8

// ???????°???°???????????????
inline double add(double a, double b){
  if(abs(a+b) < EPS*(abs(a) + abs(b))) return 0;
  return a+b;
}

struct Point{
  double x,y;
  Point() {}
  Point(double nx, double ny) : x(nx), y(ny) {}
  Point operator + (const Point & p){ return Point(add(x, p.x), add(y, p.y)); }
  Point operator - (const Point & p){ return Point(add(x,-p.x), add(y,-p.y)); }
  Point operator * (double d){ return Point(x*d, y*d); }
  double dot(const Point & p){ return add(x * p.x, y*p.y); }  //??????
  double det(const Point & p){ return add(x * p.y, -y*p.x); } //??????
  double dist(const Point & p){ return sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y)); }
  bool operator < (const Point & p) const {
    if(y != p.y) return y < p.y;
    else return x < p.x;
/*
    if(x != p.x) return x < p.x;
    else return y < p.y;
    */
  }
};

// Graham Scan
// ???????????????????¨?????????§return
// ???????????????????????????
vector<Point> convexHull(vector<Point> points){
  int n = points.size();
  sort(all(points));
  int k=0;
  vector<Point> qs(n+1);
  for(int i=0; i<n; qs[k++] = points[i++]){
    while(k>1 && (qs[k-1] - qs[k-2]).det(points[i] - qs[k-1]) < 0) k--;
  }
  for(int i=n-2,t=k; i>=0; qs[k++] = points[i--]){
    while(k>t && (qs[k-1] -qs[k-2]).det(points[i] - qs[k-1]) < 0) k--;
  }
  qs.resize(k-1);
  return qs;
}

int main(){
  int n;
  cin>>n;
  vector<Point> vec(n);
  rep(i,n){
    double x, y;
    scanf("%lf %lf", &x, &y);
    vec[i] = Point(x,y);
  }
  vector<Point> conv = convexHull(vec);

  printf("%d\n", conv.size());
  rep(i,conv.size()){
    printf("%.0f %.0f\n", conv[i].x, conv[i].y);
  }

  return 0;
}