#include <vector>
#include <cstdio>
#include <iostream>
#include <list>
#include <functional>

class Point {
public:
	Point(const int &arg_x = 0, const int &arg_y = 0) :x(arg_x), y(arg_y) {};
	Point(const Point &other):x(other.x), y(other.y) {};
	Point &operator=(const Point &other) { x = other.x; y = other.y; return *this; };
	Point operator=(Point &&other) { x = other.x; y = other.y; return *this; };
	Point operator-(const Point &) const;
	Point operator+(const Point &) const;
	int get_x() const { return x; };
	int get_y() const { return y; };
	bool operator<(const Point &) const;
	bool operator>(const Point &) const;
	bool operator==(const Point &) const;
	bool operator<=(const Point &other) const { return (((*this) < other) || (*this) == other); };
	bool operator>=(const Point &other) const { return (((*this) > other) || (*this) == other); };
	void show() const { std::printf("%d %d\n", x, y); };
private:
	int x, y;
};
class Vec {
public:
	Vec(const Point &, const Point &);
	Vec() :vec() {};
	int dot(const Vec &) const;
	int cross(const Vec &) const ;
	void show() const { std::cout << x() << " " << y() << "\n"; };
	int dist_2() const { return vec.get_x() * vec.get_x() + vec.get_y() * vec.get_y(); };
private:
	int x() const { return vec.get_x(); };
	int y() const { return vec.get_y(); };
	Point vec;
};
Point Point::operator-(const Point &other) const {
	return Point(x - other.x, y - other.y);
}
Point Point::operator+(const Point &other) const {
	return Point(x + other.x, y + other.y);
}
bool Point::operator<(const Point &other) const {
	return (y < other.y) || (y == other.y && x < other.x);
}
bool Point::operator>(const Point &other) const {
	return (y > other.y) || (y == other.y && x > other.x);
}
bool Point::operator==(const Point &other) const {
	return (x == other.x) && (y == other.y);
}
Vec::Vec(const Point &p1, const Point &p2) {
	vec = p2 - p1;
}
int Vec::dot(const Vec &other) const {
	return x() * other.x() + y() * other.y();
}
int Vec::cross(const Vec &other) const {
	return x() * other.y() - y() * other.x();
}
void sort(std::vector<Point> &vec, const int &left, const int &right) {
	if (left < right) {
		Point pivot = vec.at(left + (right - left) / 2);
		int l = left, r = right;
		while (l <= r) {
			while (pivot > vec.at(l)) { ++l; }
			while (pivot < vec.at(r)) { --r; }
			if (l <= r) {
				Point temp{ vec.at(l) };
				vec.at(l) = vec.at(r); vec.at(r) = temp;
				++l; --r;
			}
		}
		sort(vec, left, r); sort(vec, l, right);
	}
}
std::list<Point>::iterator prev(std::list<Point>::iterator i) {
	return --i;
}
std::list<Point> func(const std::vector<Point> &vector, const std::function<bool(const Vec&, const Vec&)> &lambda) {
	std::list<Point> stack;
	stack.push_back(vector.at(0)); stack.push_back(vector.at(0));
	for (auto p : vector) {
		auto e = stack.end();
		--e;
		while (!(lambda(Vec(p, *e), Vec(*e, *prev(e))))) {
			--e;
			stack.pop_back();
		}
		stack.push_back(p);
	}
	stack.pop_front(); stack.pop_front();
	return stack;
}
int main() {
	int n;
	std::cin >> n;
	std::vector<Point> vector;
	for (auto i = 0; i < n; ++i) {
		int x, y;
		std::cin >> x >> y;
		vector.push_back(Point(x, y));
	}
	sort(vector, 0, vector.size() - 1);
	auto list1 = func(vector, [](const Vec &a, const Vec &b)->bool {return (a.cross(b) <= 0); });
	auto list2 = func(vector, [](const Vec &a, const Vec &b)->bool {return (a.cross(b) >= 0); });
	list1.pop_back(); list2.pop_front();
	std::printf("%d\n", list1.size() + list2.size());
	for (auto p1 = list1.begin(); p1 != list1.end();++p1) {
		p1->show();
	}
	for (auto p2 = list2.end(); p2 != list2.begin();) {
		(--p2)->show();
	}

	return 0;
}

Measured memory_bytes: 4676