#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cassert>
struct Point {
long long x, y;
int id;
long long norm2() const {
return x*x+y*y;
}
Point operator-(const Point& p) const {
return Point{x-p.x, y-p.y, 0};
}
};
long long det(const Point& a, const Point& b) {
return a.x * b.y - a.y * b.x;
}
bool right_rotate(const Point& a, const Point& b, const Point& c) {
return det(a-b, c-b) >= 0;
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(0); std::cout.tie(0);
int n; std::cin >> n;
std::vector<Point> points;
for (int i = 1; i <= n; ++i) {
long long x, y; std::cin >> x >> y;
points.push_back(Point{x, y, i});
}
auto it = min_element(points.begin(), points.end(), [](const Point& a, const Point& b){
return a.x < b.x || (a.x == b.x && a.y < b.y);
});
std::swap(*it, points[0]);
for (int i = 1; i < n; ++i) {
points[i].x -= points[0].x;
points[i].y -= points[0].y;
}
points[0].x = points[0].y = 0;
std::sort(points.begin()+1, points.end(), [](const Point& a, const Point& b) {
return a.y * b.x < b.y * a.x || (a.y * b.x == b.y * a.x && a.norm2() < b.norm2());
});
points.push_back(points[0]);
std::vector<Point> conv_hull{points[0], points[1]};
for (int i = 2; i <= n; ++i) {
conv_hull.push_back(points[i]);
for (int j = (int)conv_hull.size()-1; j >= 2; --j) {
if (right_rotate(conv_hull[j-2], conv_hull[j-1], conv_hull[j])) {
conv_hull[j-1] = conv_hull[j];
conv_hull.pop_back();
} else {
break;
}
}
}
assert(conv_hull.size() >= 4u);
assert(conv_hull.front().id == conv_hull.back().id);
std::cout << (int)conv_hull.size()-1 << std::endl;
for (int i = 0; i+1 < (int)conv_hull.size(); ++i) {
const auto& it = conv_hull[i];
std::cout << (int)it.x << ' ' << (int)it.y << '\n';
}
return 0;
}