#include<bits/stdc++.h>
#define cmin(a,b) (a>(b)?a=(b),1:0)
#define cmax(a,b) (a<(b)?a=(b),1:0)
#define dmin(a,b) ((a)<(b)?(a):(b))
#define dmax(a,b) ((a)>(b)?(a):(b))
namespace io
{
	int F()
	{
		 int F=1,n=0;
		 char ch;
		 while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
		 ch=='-'?F=0:n=ch-'0';
		 while((ch=getchar())>='0'&&ch<='9')n=n*10+ch-'0';
		 return F?n:-n;
	}
	long long G()
	{
		 long long F=1,n=0;
		 char ch;
		 while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
		 ch=='-'?F=0:n=ch-'0';
		 while((ch=getchar())>='0'&&ch<='9')n=n*10+ch-'0';
		 return F?n:-n;
	}
}
namespace Geometry
{
	typedef long long Scalar;
	
	Scalar Abs(Scalar x) {
		return x > 0 ? x : -x;
	}
	
	const Scalar eps = 1e-8;
	
	const double pi = acos(-1);
	
	struct Point;
	typedef Point Vector;
	
	struct Point
	{
		Scalar x,y;
		Scalar len() const {
			return sqrt(x*x + y*y);
		}
		Scalar len2() const {
			return x * x + y * y;
		}
		Vector uni() const {
            Scalar l = len();
            return (Vector){x / l, y / l};
        }
		Point operator + (const Vector &b) const {
			return (Point){x + b.x, y + b.y};
		}
		Vector operator - (const Point &b) const {
			return (Vector){x - b.x, y - b.y};
		}
		Point rotate(double ang) const {
			return *this;
		}
		Point rotate(const Point &o, double ang) const {
			return *this;
		}
		void print() {
			printf("(%.3lf,%.3lf)\n",(double)x,(double)y);
		}
	};
	
	bool operator <(const Point &x,const Point &y)
	{
	    if(Abs(x.x-y.x)>eps)return x.x<y.x;
	    return x.y<y.y;
	}
	bool operator == (const Point &x, const Point &y) {
		return Abs(x.x - y.x) <= eps && Abs(x.y - y.y) <= eps;
	}
	Scalar operator * (const Vector &x, const Vector &y) {
		return x.x * y.y - x.y * y.x;
	}
	Scalar operator / (const Vector &x, const Vector &y) {
		return x.x * y.x + x.y * y.y;
	}
	Vector operator * (const Scalar &x, const Vector &y) {
		return (Vector){x * y.x, x * y.y};
	}
	Vector operator * (const Vector &y, const Scalar &x) {
		return (Vector){x * y.x, x * y.y};
	}
	Vector operator / (const Vector &x, const Scalar &y) {
		return (Vector){x.x / y, x.y / y};
	}
	
	struct Line
	{
		Point o;
		Vector l; // unit length
	};
	
	Scalar dist(const Point &x, const Line &y) { //signed
		return y.l * (x - y.o);
	}
	
	Point footpoint(const Point &x, const Line &y) {
		Scalar d=dist(x,y);
		return x - d * y.l.rotate(pi / 2);
	}
	
	Point intersect(const Line &x, const Line &y) {
		Scalar d1 = dist(x.o, y);
		Scalar d2 = dist(x.o + x.l, y);
		return x.o + d1 / (d1 - d2) * x.l;
	}
	
	struct Seg
	{
		Point x,y;
		Scalar len() const {
			return (x - y).len();
		}
	};
	
	Line line(const Seg &x) {
		return (Line){x.x, (x.y - x.x) / x.len()};
	}
	
	Scalar dist(const Point &o, const Seg &l) {
		if(Abs((l.y - l.x) * (o - l.x)) <= eps)
		{
			Scalar d1 = (o - l.x).len();
			Scalar d2 = (o - l.y).len();
			return (Abs(d1 + d2 - l.len()) <= eps) ? 0 : std::min(d1, d2);
		}
		else
		{
			if((l.y - l.x) / (o - l.x) < 0) return (o - l.x).len();
			if((l.x - l.y) / (o - l.y) < 0) return (o - l.y).len();
			return dist(o, line(l));
		} 
	}
	
	int convexHull(Point *p, int n, Point *s) { // return # of points on the convex hull + 1
		std::sort(p + 1, p + n + 1, [](const Point &x, const Point &y)  { return x.x != y.x ? x.x < y.x : x.y < y.y;});
		int ts = 0;
		for(int i = 1; i <= n; ++i)
			if(i == 1 || !(p[i] == p[i-1]))
			{
				while(ts > 1 && (p[i] - s[ts-1]) * (s[ts] - s[ts-1]) > 0)
					--ts;
				s[++ts] = p[i];
			}
		int cl = ts;
		for(int i = n - 1; i; --i)
			if(!(p[i] == p[i+1]))
			{
				while(ts > cl && (p[i] - s[ts-1]) * (s[ts] - s[ts-1]) > 0)
					--ts;
				s[++ts] = p[i];
			}
		return ts - 1;
	}
	
	struct Circle
	{
		Point o;
		Scalar r;
		bool in(const Circle &y) const {
			return (o - y.o).len() + r <= y.r;
		}
	};
	
	std::pair<Point, Point> intersect(const Circle &c, const Line &l) {
		Point p = footpoint(c.o, l);
		Scalar k = c.r * c.r - (c.o - p).len2();
		k = k < 0 ? 0 : sqrt(k);
		return std::make_pair(p + k * l.l, p - k * l.l);
	}
	
	std::pair<Point, Point> intersect(const Circle &x, const Circle &y) {
		Scalar d = (x.o - y.o).len();
		double ang = acos((x.r * x.r + d * d - y.r * y.r)/(2 * x.r * d));
		Vector v = x.r * (y.o - x.o) / d;
		return std::make_pair(x.o + v.rotate(ang), x.o + v.rotate(-ang));
	}
	
	std::pair<Line, Line> tangentLine(const Point &x, const Circle &c) {
		if(Abs((x - c.o).len() - c.r) <= eps) {
			Line l = (Line){x, (x - c.o).uni().rotate(pi/2)};
			return std::make_pair(l,l);
		}
		Scalar d1 = (c.o - x).len();
		double ang = asin(c.r / d1);
		Vector v = (c.o - x).uni();
		return std::make_pair((Line){x, v.rotate(ang)}, (Line){x, v.rotate(-ang)});
	}
	
	std::pair<Point, Point> tangentPoint(const Point &x, const Circle &c) {
		auto tl = tangentLine(x, c);
		Scalar d1 = (c.o - x).len();
		double ang = asin(c.r / d1);
		Scalar d2 = d1 * cos(ang);
		return std::make_pair(x + d2 * tl.first.l, x + d2 * tl.second.l);
	}
	
	std::pair<Seg, Seg> outerTSeg(Circle x, Circle y) {
		int sw=0;
		if(x.r > y.r)std::swap(x, y),sw=1;
		if(Abs(x.r + (x.o - y.o).len() - y.r) < eps)
		{
			auto s = intersect(x, y).first;
			return std::make_pair((Seg){s, s}, (Seg){s, s});
		}
		y.r -= x.r;
		auto p = tangentPoint(x.o, y);
		auto q = tangentLine(x.o, y);
		Vector b1 = q.first.l.rotate(pi/2) * x.r;
		Vector b2 = q.second.l.rotate(-pi/2) * x.r;
		auto ret = std::make_pair((Seg){x.o + b1, p.first + b1}, (Seg){x.o + b2, p.second + b2});
		if(sw) std::swap(ret.first.x, ret.first.y), std::swap(ret.second.x, ret.second.y);
		return ret;
	}
	
	std::pair<Seg, Seg> innerTSeg(const Circle &x, Circle y) { // x.r + y.r cannot be too small
		if(Abs((x.o - y.o).len() - x.r - y.r) < eps)
		{
			auto s = intersect(x, y).first;
			return std::make_pair((Seg){s, s}, (Seg){s, s});
		}
		y.r += x.r;
		auto p = tangentPoint(x.o, y);
		Vector b1 = (p.first - y.o).uni() * x.r;
		Vector b2 = (p.second - y.o).uni() * x.r;
		return std::make_pair((Seg){x.o - b1, p.first - b1}, (Seg){x.o - b2, p.second - b2});
	}
}

int main()
{
	int n=io::F();
	using namespace Geometry;
	Point p[111111],s[111111];
	for(int i=1;i<=n;++i)p[i]=(Point){io::F(),io::F()};
	int ts=convexHull(p,n,s);
	printf("%d\n",ts);
	int mp=1;
	Point ss=s[1];
	for(int i=1;i<=ts;++i)
		if(s[i].y<ss.y||(s[i].y==ss.y&&s[i].x<ss.x))ss=s[i],mp=i;
	for(int i=mp;i<=ts;++i)
		printf("%lld %lld\n",s[i].x,s[i].y); 
	for(int i=1;i<mp;++i)
		printf("%lld %lld\n",s[i].x,s[i].y);
	return 0;
}



Measured memory_bytes: 5596