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: Accepted)

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<climits>
#include<string>
#include<set>
#include<map>
using namespace std;
#define rep(i,n) for(int i=0;i<((int)(n));i++)
#define reg(i,a,b) for(int i=((int)(a));i<=((int)(b));i++)
#define irep(i,n) for(int i=((int)(n))-1;i>=0;i--)
#define ireg(i,a,b) for(int i=((int)(b));i>=((int)(a));i--)
typedef long long int lli;
typedef pair<int,int> mp;
#define fir first
#define sec second
#define IINF INT_MAX
#define LINF LLONG_MAX

struct pos{
	double x,y;
	double norm,norm2;
	pos tov(pos a){
		return (a-(*this));
	}
	pos operator+(pos a)const{
		pos res=a;
		res.x+=x; res.y+=y;
		res=pos(res.x,res.y);
		return res;
	}
	pos operator-(pos a)const{
		pos res=(*this);
		res.x-=a.x; res.y-=a.y;
		res=pos(res.x,res.y);
		return res;
	}
	pos scalar(double a){
		pos res=(*this);
		res.x*=a; res.y*=a;
		res=pos(res.x,res.y);
		return res;
	}
	double dot(pos a){
		return x*a.x + y*a.y;
	}
	double cross(pos a){
		return x*a.y - y*a.x;
	}
	double theta(pos a){
		double nt=dot(a)/(norm*a.norm);
		nt=acos(max(-1.0,min(1.0,nt)));
		double ns=(cross(a)/(norm*a.norm));
		if(ns<0)nt*=-1;
		return nt;
	}
	pos(double ix,double iy){
		x=ix; y=iy;
		norm2=x*x+y*y;
		norm=sqrt(norm2);
	}
	pos(){}
	string str(){
		char ns[50];
		sprintf(ns,"(%lf %lf)",x,y);
		return	string(ns);
	}
	static pos polar(double r,double t){
		return pos(r*cos(t),r*sin(t));
	}
	bool  operator<(pos a) const{
		//if(x!=a.x)return (x<a.x);
		//return (y<a.y);
		if(y!=a.y)return (y<a.y);
		return (x<a.x);
	}	
	bool operator>(pos a) const{
		return (a<(*this));
	}	
};

struct line{
	pos p,q;
	pos vec;
	string str(){
		return ("("+p.str()+"-"+q.str()+")");
	}
	bool iscross(line a){
		double da,db;
		da=vec.cross( p.tov(a.p) );
		db=vec.cross( p.tov(a.q) );
		if(da*db>=0)return false;
		da=a.vec.cross( a.p.tov(p) );
		db=a.vec.cross( a.p.tov(q) );
		return (da*db<0);
	}
	line(pos ip,pos iq){
		p=ip; q=iq;
		vec=p.tov(q);
	}
	line(){}
	double dist(pos a){
		if(p.tov(a).dot( p.tov(q) )<0)return p.tov(a).norm;
		if(q.tov(a).dot( q.tov(p) )<0)return q.tov(a).norm;
		return abs(vec.cross(p.tov(a))/vec.norm);
	}
	double dist(line a){
		if(iscross(a))return 0;
		return min( min(dist(a.p),dist(a.q)) , min(a.dist(this->p),a.dist(this->q)));
	}
};

double lowofcos_getcos(double a,double b,double c){
	return ((a*a+b*b-c*c)/(2*a*b));
}

struct circle{
	pos p;
	double r;
	
	line koten(circle a){
		pos cv=p.tov(a.p);
		double br=atan2(cv.y,cv.x);
		double dr=acos(lowofcos_getcos( r, cv.norm, a.r));
		
		pos p1= p+pos::polar(r,br+dr);
		pos p2= p+pos::polar(r,br-dr);
		
		if(p1>p2)swap(p1,p2);
		return line(p1,p2);
	}
	circle(pos ip,double ir){
		p=ip; r=ir;
	}
	circle(){}
};

struct polygon{
	vector<pos> ps;
	polygon(){}
	double area(){
		double res=0;
		rep(i,ps.size()){
			pos no=ps[i],to=ps[(i+1)%ps.size()];
			res+=(no.x+to.x)*(no.y-to.y);
		}
		return abs(res)/2;
	}
	polygon(pos a,pos b){
		ps.push_back(a);
		ps.push_back(pos(a.x,b.y));
		ps.push_back(b);
		ps.push_back(pos(b.x,a.y));
	}
	line gete(int a){
		return line(ps[a],ps[(a+1)%ps.size()]);
	}
	int isin(pos a){
		//?????´??????2,?????£????????????1,?????????0
		double as=0;
		rep(i,ps.size()){
			line ne=gete(i);
			if(ne.dist(a)<=0)return 1;
			pos v1=a.tov(ne.p);
			pos v2=a.tov(ne.q);
			as+=v1.theta(v2);
		}
		if(abs(as)<1e-6)return 0;
		return 2;
	}
	polygon convex_full(){
		polygon res;
		int ns=ps.size();
		vector<pos> vs(2*ns);
		sort(ps.begin(),ps.end());
		int k=0;
		//????????????
		rep(i,ns){
			pos np=ps[i];
			while(k>1 && vs[k-2].tov(vs[k-1]).cross(vs[k-1].tov(np))<-1e-6)k--;
			vs[k]=np; k++;
		}
		int t=k;
		//????????????
		ireg(i,0,ns-2){
			pos np=ps[i];
			while(k>t && vs[k-2].tov(vs[k-1]).cross(vs[k-1].tov(np))<-1e-6)k--;
			vs[k]=np; k++;
		}
		vs.resize(k-1);//???????????????????????£??????????????§???
		
		swap(vs,res.ps);
		return res;
	}
	polygon mult(polygon a){
		return a;
	}
};




int main(void){
	/*
	double a,b,c;
	circle c1,c2;
	scanf("%lf%lf%lf",&a,&b,&c);
	c1=circle(pos(a,b),c);
	scanf("%lf%lf%lf",&a,&b,&c);
	c2=circle(pos(a,b),c);
	line ne=c1.koten(c2);
	printf("%lf %lf %lf %lf\n",ne.p.x,ne.p.y,ne.q.x,ne.q.y);
	return 0;
	*/
	
	int n;
	scanf("%d",&n);
	polygon pl;
	rep(i,n){
		double p,q;
		scanf("%lf%lf",&p,&q);
		pl.ps.push_back(pos(p,q));
	}
	
	polygon cv = pl.convex_full();
	n=cv.ps.size();
	printf("%d\n",n);
	rep(i,n){
		printf("%d %d\n",(int)cv.ps[i].x,(int)cv.ps[i].y);
	}
	return 0;
	
	int qn;
	scanf("%d",&qn);
	rep(i,qn){
		double p,q;
		scanf("%lf%lf",&p,&q);
		printf("%d\n",pl.isin(pos(p,q)));
	}
	
	return 0;
}