Problem:
Convex Hull

Find the convex hull of a given set of points P. In other words, find the smallest convex polygon containing all the points of P. Here, in a convex polygon, all interior angles are less than or equal to 180 degrees.

Please note that you should find all the points of P on both corner and boundary of the convex polygon.

Input

n
x1 y1
x2 y2
:
xn yn

The first integer n is the number of points in P. The coordinate of the i-th point pi is given by two integers xi and yi.

Output

In the first line, print the number of points on the corner/boundary of the convex polygon. In the following lines, print x y coordinates of the set of points.
The coordinates should be given in the order of counter-clockwise visit of them starting from the point in P with the minimum y-coordinate, or the leftmost such point in case of a tie.

Constraints

3 ≤ n ≤ 100000

-10000 ≤ xi, yi ≤ 10000

No point in the P will occur more than once.

Sample Input 1

7
2 1
0 0
1 2
2 2
4 2
1 3
3 3

Sample Output 1

5
0 0
2 1
4 2
3 3
1 3

Sample Input 2

4
0 0
2 2
0 2
0 1

Sample Output 2

4
0 0
2 2
0 2
0 1

Solution in C++ (judge verdict: Runtime Error)

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i = (a); i < (b); ++i)
#define per(i, a, b) for(int i = (b) - 1; i >= (a); --i)
#define sz(a) (int)a.size()
#define de(c) cout << #c << " = " << c << endl
#define dd(c) cout << #c << " = " << c << " "
#define all(a) a.begin(), a.end()
#define pw(x) (1ll<<(x))
#define endl "\n"
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
typedef vector<int> vi;

typedef db T;
const db eps = 1e-9 , pi = acosl(-1.);
int sgn(T x){return (x>eps)-(x<-eps);}
struct P{
  T x,y; P(){} P(T x,T y):x(x),y(y){}
  P operator - (const P&b) const {return P(x-b.x,y-b.y);}
  P operator + (const P&b) const {return P(x+b.x,y+b.y);}
  T operator * (const P&b) const {return x*b.x+y*b.y;}
  T operator / (const P&b) const {return x*b.y-y*b.x;}
  P operator * (const T&k) const {return P(x*k,y*k);}
  P operator / (const T&k) const {return P(x/k,y/k);}
	bool operator < (const P&b) const {return sgn(x-b.x)?x<b.x:y<b.y;}
};
T norm(P a){return a*a;}
T abs(P a) {return sqrtl(norm(a));}
P proj(P p,P a,P b){return (b-a)*((p-a)*(b-a)/norm(b-a))+a;}
P reflect(P p,P a,P b){return proj(p,a,b)*2-p;}
T cross(P o,P a,P b){return (a-o)/(b-o);}
int crossOp(P o,P a,P b){return sgn(cross(o,a,b));}
bool onPS(P p,P s,P t){return sgn((t-s)/(p-s))==0&&sgn((p-s)*(p-t))<=0;}
struct L{ P s,t;L(){} L(P s,P t):s(s),t(t){}};
P insLL(L a,L b){ // line x line
	P s = a.s - b.s , v = a.t - a.s , w = b.t - b.s;
	db k1 = s / w , k2 = w / v;
	if(sgn(k2) == 0) return abs(b.s - a.s) < abs(b.t - a.s) ? b.s : b.t;
	return a.s + v * (k1 / k2);
}
bool isSS(L a,L b){ // seg x seg , replace x->y to accelerate
	T c1=(a.t-a.s)/(b.s-a.s),c2=(a.t-a.s)/(b.t-a.s);
	T c3=(b.t-b.s)/(a.s-b.s),c4=(b.t-b.s)/(a.t-b.s);
	return sgn(c1) * sgn(c2) <= 0 && sgn(c3) * sgn(c4) <= 0 &&
		sgn(max(a.s.x,a.t.x) - min(b.s.x,b.t.x)) >= 0 &&
		sgn(max(b.s.x,b.t.x) - min(a.s.x,a.t.x)) >= 0 &&
		sgn(max(a.s.y,a.t.y) - min(b.s.y,b.t.y)) >= 0 &&
		sgn(max(b.s.y,b.t.y) - min(a.s.y,a.t.y)) >= 0;
}
db disPL(P p,L a){return fabs((a.t-a.s)/(p-a.s)) / abs(a.t-a.s);}
db disPS(P p,L a){ // p x seg dis
	if(sgn((a.t-a.s)*(p-a.s)) == -1) return abs(p-a.s);
	if(sgn((a.s-a.t)*(p-a.t)) == -1) return abs(p-a.t);
	return disPL(p,a);
}
db disSS(L a,L b){ // seg x seg dis
	if(isSS(a,b)) return 0;
	return min(min(disPS(a.s,b),disPS(a.t,b)),min(disPS(b.s,a),disPS(b.t,a)));
}
typedef vector<P> polygon;
polygon convex(polygon A){ // counter-clockwise , <= : <=180 , < : <180
  int n=sz(A),m=0;
  polygon B;B.resize(n+1);
  sort(all(A));
  rep(i,0,n){
    while(m > 1 && sgn((B[m-1]-B[m-2])/(A[i]-B[m-2]))<0) --m;
    B[m++]=A[i];
  }
  per(i,0,n-1){
    while(m > 1 && sgn((B[m-1]-B[m-2])/(A[i]-B[m-2]))<0) --m;
    B[m++]=A[i];
  }
  B.resize(m);
  if(sz(B) > 1) B.pop_back();
  return B;
}
T area(polygon A) { // multiple 2 with integer type
	T res=0;
	rep(i,0,sz(A)) res+=A[i]/(A[(i+1)%sz(A)]);
	return fabs(res) / 2;
}
bool isconvex(polygon A){ // counter-clockwise
	bool ok=1;int n=sz(A);
	rep(i,0,2) A.pb(A[i]);
	rep(i,0,n) ok&=((A[i+1]-A[i])/(A[i+2]-A[i]))>=0;
	return ok;
}
int inPpolygon(P p,polygon A){ // -1 : on , 0 : out , 1 : in
	int res=0;
	rep(i,0,sz(A)){
		P u=A[i],v=A[(i+1)%sz(A)];
		if(onPS(p,u,v)) return -1;
		T cross = sgn((v-u)/(p-u)) , d1 = sgn(u.y-p.y) , d2 = sgn(v.y-p.y);
		if(cross > 0 && d1 <= 0 && d2 > 0) ++res;
		if(cross < 0 && d2 <= 0 && d1 > 0) --res;
	}
	return res != 0;
}

P a, b, c, d;
polygon poly;

int main() {
	std::ios::sync_with_stdio(0);
	std::cin.tie(0);
//	freopen("a.in", "r", stdin);
//	freopen("a.out", "w", stdout);
	int q;
	cin >> q;
	cout << setiosflags(ios::fixed);
	cout << setprecision(0);
	while(q--) {
		cin >> a.x >> a.y;
		poly.pb(a);
	}
	poly = convex(poly);
	cout << sz(poly) << endl;
	int p = 0;
	rep(i, 0, sz(poly)) if(poly[i].y < poly[p].y || (poly[i].y == poly[p].y && poly[i].x < poly[p].x)) p = i;
	rep(i, p, sz(poly)) cout << poly[i].x << " " << poly[i].y << endl;
	rep(i, 0, p) cout << poly[i].x << " " << poly[i].y << endl;
	return 0;
}