#include <cmath>

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

typedef double D;
const D EPS = 1e-8;
const D INF = 1e10;
const D PI = M_PI;
int sign(D a, D b = 0.0) {
    if(a < b - EPS) return -1;
    if(a > b + EPS) return +1;
    return 0;
}
struct P {
    D x, y;
    P(D xs, D ys) : x(xs), y(ys) { }
    P() { }
};
P operator +(P a, P b) { return P(a.x + b.x, a.y + b.y); }
P operator -(P a, P b) { return P(a.x - b.x, a.y - b.y); }
P operator *(P p, D s) { return P(p.x * s, p.y * s); }
bool operator <(P a, P b) {
    if(sign(a.y, b.y) != 0) return a.y < b.y;
    return a.x < b.x;
}
P vec(P from, P to) { return to - from; }
D inp(P a, P b) { return a.x*b.x + a.y*b.y; }
D outp(P a, P b) { return a.x*b.y - a.y*b.x; }
D norm(P p) { return inp(p, p); }
D abs(P p) { return sqrt(norm(p)); }
bool eq(P a, P b) { return abs(a - b) < EPS; }
D arg(P p) { return atan2(p.y, p.x); }
P rot90(P p) {
    return P(-p.y, p.x);
}
P rot(P p, D radian) {
    P q;
    q.x = cos(radian)*p.x - sin(radian)*p.y;
    q.y = sin(radian)*p.x + cos(radian)*p.y;
    return q;
}
int ccw(P a, P b, P c) {
    b = vec(a, b); c = vec(a, c);

    // a - b - c ????????????????????¨???
    if(sign(outp(b, c)) > 0) return +1; // ???????¨???????
    if(sign(outp(b, c)) < 0) return -1; // ????¨???????

    // a - b - c ?????´??????????????¶??¨???
    if(sign(inp(b, c)) < 0) return +2; // c - a - b
    if(norm(b) < norm(c))   return -2; // a - b - c
    return 0;                          // a - c - b
}
struct L {
    P a, b;
    L(P as, P bs) : a(as), b(bs) { }
};
P projection(L l, P p) { // ??´???l???????????????p?????????
    P a = vec(l.a, l.b);
    P b = vec(l.a, p);
    D t = inp(b, a) / norm(a);
    return l.a + a * t;
}
P reflection(L l, P p) { // ??´???l???????????????p???????°?
    return p + vec(p, projection(l, p)) * 2;
}
// ????????¨???
bool iSP(L s, P p) {
    return ccw(s.a, s.b, p) == 0;
}
D dSP(L s, P p) {
    P r = projection(s, p);
    if(iSP(s, r)) return abs(vec(p, r)); // ?????????s????????????
    return min(abs(vec(p, s.a)), abs(vec(p, s.b))); // ?????????s????????????
}
// ??´?????¨???
bool iLP(L l, P p) {
    return abs(ccw(l.a, l.b, p)) != 1;
}
D dLP(L l, P p) {
    return abs(vec(p, projection(l, p)));
}
// ????????¨??????
bool iSS(L s, L t) { // ????????????
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
        ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
D dSS(L s, L t) {
    if(iSS(s, t)) return 0;
    return min(min(dSP(s, t.a), dSP(s, t.b)),
            min(dSP(t, s.a), dSP(t, s.b)));
}
// ??´?????¨??´???
bool iLL(L l, L m) {
    return sign(outp(vec(l.a, l.b), vec(m.a, m.b))) != 0 || // ????????§??????
        sign(outp(vec(l.a, l.b), vec(l.a, m.a))) == 0; // ????????´???
}
D dLL(L l, L m) {
    return iLL(l, m) ? 0.0 : dLP(l, m.a);
}
/* ?????????????????¨??????iSS(s,t)????¢???????????????¨ */
P cLL(L l, L m) {
    D d = outp(vec(m.a, m.b), vec(l.a, l.b));
    return l.a + vec(l.a, l.b) * outp(vec(m.a, m.b), vec(l.a, m.b)) * (1.0 / d);
}
// ??´?????¨??????
bool iLS(L l, L s) {
    return sign(outp(vec(l.a, l.b), vec(l.a, s.a))) *
        sign(outp(vec(l.a, l.b), vec(l.a, s.b))) <= 0;
}
D dLS(L l, L s) {
    if(iSS(l, s)) return 0.0;
    return min(dLP(l, s.a), dLP(l, s.b));
}

typedef vector<P> G;
P at(G g, int i) { return g[i % g.size()]; }
D areaG(G g) {
    D res = 0.0;
    for(int i = 0; i < (int)g.size(); i++) {
        res += outp(at(g, i), at(g, i + 1));
    }
    return res / 2.0;
}
// ON = 0, IN = 1, OUT = -1
int containsGP(G g, P p) {
    int side = -1;
    for(int i = 0; i < (int)g.size(); i++) {
        if(ccw(at(g, i), at(g, i + 1), p) == 0) return 0;
        P a = vec(p, at(g, i));
        P b = vec(p, at(g, i + 1));
        if(a.y > b.y) swap(a, b);
        if(sign(a.y) <= 0 && sign(b.y) > 0 && sign(outp(a, b)) > 0) side *= -1;
    }
    return side;
}
G convex_hull(vector<P> ps) {
    int N = ps.size();
    int k = 0; // ??????????§??????????????????°
    sort(ps.begin(), ps.end());
    G res(N * 2);
    for(int i = 0; i < N; i++) {
        // ????¨?????????????????????????????????£???????????????????????????
        while(k >= 2 && ccw(res[k - 2], res[k - 1], ps[i]) == -1) k--;
        res[k++] = ps[i];
    }
    int t = k + 1;
    // ????????????????????? (??????????????????)
    // ??????????????? (??????????????????????????¨???????????????????????????????\?)
    for(int i = N - 2; i >= 0; i--) {
        while(k >= t && ccw(res[k - 2], res[k - 1], ps[i]) == -1) k--;
        res[k++] = ps[i];
    }
    res.resize(k - 1);
    return res;
}
struct C {
    P p; D r;
    C(P ps, D rs) : p(ps), r(rs) { }
    C() { }
};

int main() {
    int N; cin >> N;
    vector<P> ps(N);
    for(int i = 0; i < N; i++) cin >> ps[i].x >> ps[i].y;
    G hull = convex_hull(ps);
    cout << hull.size() << endl;
    for(P p : hull) cout << p.x << ' ' << p.y << endl;
}

Measured memory_bytes: 4692