#include <bits/stdc++.h>
using namespace std;
//Построение выпуклой оболочки обходом Грэхэма

struct pt {
  double x, y;
};

bool cmp(pt a, pt b) { return a.x < b.x || a.x == b.x && a.y < b.y; }

bool cw(pt a, pt b, pt c) {  // по часовой стрелке
  return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) < 0;
}

bool ccw(pt a, pt b, pt c) {  // против часовой стрелки
  return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) > 0;
}

void convex_hull(vector<pt>& a) {
  if (a.size() == 1) return;       // всего одна точка
  sort(a.begin(), a.end(), &cmp);  // сортировка по x
  pt p1 = a[0], p2 = a.back();  // самая  левая и правая вершины
  vector<pt> up, down;  // верхнее и нижнее подмножество
  up.push_back(p1);
  down.push_back(p1);
  for (size_t i = 1; i < a.size(); ++i) {
    if (i == a.size() - 1 || cw(p1, a[i], p2)) {  //  в верхнее множество
      while (up.size() >= 2 && !cw(up[up.size() - 2], up[up.size() - 1], a[i]))
        up.pop_back();
      up.push_back(a[i]);
    }
    if (i == a.size() - 1 || ccw(p1, a[i], p2)) {  // в нижнее
      while (down.size() >= 2 &&
             !ccw(down[down.size() - 2], down[down.size() - 1], a[i]))
        down.pop_back();
      down.push_back(a[i]);
    }
  }
  a.clear();
  for (size_t i = 0; i < up.size(); ++i) a.push_back(up[i]);
  for (size_t i = down.size() - 2; i > 0; --i) a.push_back(down[i]);
}

double sq(const vector<pt>& a) {
  double res = 0;
  for (size_t i = 0; i < a.size(); i++) {
    pt p1 = i ? a[i - 1] : a.back(), p2 = a[i];
    res += (p1.x - p2.x) * (p1.y + p2.y);
  }
  return fabs(res) / 2;
}

int main() {
  int n;
  cin >> n;
  vector<pt> a(n);
  for (int i = 0; i < n; i++) cin >> a[i].x >> a[i].y;
  convex_hull(a);
  cout << a.size() << "\n";
  for (auto& i : a) cout << i.x << ' ' << i.y << "\n";
  cout << fixed << setprecision(1) << sq(a);
  return 0;
}