#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
using namespace std;
using ll = long long ;
using P = pair<int,int> ;
using pll = pair<long long,long long>;
constexpr int INF = 1e9;
constexpr long long LINF = 1e17;
constexpr int MOD = 1000000007;
constexpr double PI = 3.14159265358979323846;
constexpr double EPS = 1e-10;
constexpr bool eq(const double& x,const double& y){return fabs(x-y)<EPS;}

template<typename T>
struct Point{
    T x=0,y=0;
    constexpr Point(T x=0,T y=0):x(x),y(y){}
    constexpr bool operator==(const Point& r)const{return eq(x,r.x)&&eq(y,r.y);};
    constexpr bool operator!=(const Point& r)const{return !(*this==r);};
    constexpr bool operator<(const Point& r)const{return (eq(x,r.x))?(y<r.y):(x<r.x);};
    //constexpr bool operator>(const Point& r)const{return (eq(x,r.x))?(y>r.y):(x>r.x);};
    constexpr Point operator+(const Point& r)const{return Point(*this)+=r;}
    constexpr Point operator+=(const Point& r){
        x+=r.x;y+=r.y;
        return *this;
    }
    constexpr Point operator-(const Point& r)const{return Point(*this)-=r;}
    constexpr Point operator-=(const Point& r){
        x-=r.x;y-=r.y;
        return *this;
    }
    constexpr Point operator*(const T& r)const{return Point(*this)*=r;}
    constexpr Point operator*=(const T& r){
        x*=r;y*=r;
        return *this;
    }
    constexpr Point operator/(const T& r)const{return Point(*this)/=r;}
    constexpr Point operator/=(const T& r){
        x/=r;y/=r;
        return *this;
    }
};
using point = Point<double>;
double norm(const point& a){return a.x*a.x+a.y*a.y;}
double abs(const point& a){return sqrt(a.x*a.x+a.y*a.y);}
double dot_product(const point& a,const point& b){return a.x*b.x+a.y*b.y;}
double cross_product(const point& a,const point& b){return a.x*b.y-a.y*b.x;}
point projection(const point& p,const point& b){return b*dot_product(p,b)/norm(b);}
double area(const point& a,const point& b,const point& c){return cross_product(b-a,c-a)/2.0;}


point pp[100005];

int main(){
    int n;
    cin >> n;
    rep(i,n) cin >> pp[i].x >> pp[i].y;
    sort(pp,pp+n);
    vector<point> ans = {pp[0]};
    int i = 1;
    while(i<n){
        point last = ans.back();
        if(ans.size()>=2){
            point llast = ans[ans.size()-2];
            if(area(last,llast,pp[i])>0){
                ans.pop_back();
                if(ans.size()>=2){
                    while(area(ans.back(),ans[ans.size()-2],pp[i])>0){
                        ans.pop_back();
                        if(ans.size()==1) break;
                    }
                }
                ans.push_back(pp[i]);
                ++i;
            }else{
                ans.push_back(pp[i]);
                ++i;
            }
        }else{
            ans.push_back(pp[i]);
            ++i;
        }
    }
    i=n-2;
    vector<point> anss = {pp[n-1]};
    while(i>=0){
        point last = anss.back();
        if(anss.size()>=2){
            point llast = anss[anss.size()-2]; 
            if(area(last,llast,pp[i])>0){
                anss.pop_back();
                if(anss.size()>=2){
                    while(area(anss.back(),anss[anss.size()-2],pp[i])>0){
                        anss.pop_back();
                        if(anss.size()==1) break;
                    }
                }
                anss.push_back(pp[i]);
                --i;
            }else{
                anss.push_back(pp[i]);
                --i;
            }
        }else{
            anss.push_back(pp[i]);
            --i;
        }
    }
    i=0;
    for(int j=ans.size()-1;j>=1;j--){
        if(ans[j-1].y>ans[j].y){i = j;break;}
    }
    for(int j=1;j<anss.size()-1;j++) ans.push_back(anss[j]);
    int m = ans.size();
    cout << m << endl;
    rep(j,m){
        cout << ans[(i+j)%m].x << " " << ans[(i+j)%m].y << endl;
    }

    return 0;
}


Measured memory_bytes: 6864