#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

typedef struct Point
{
  int x,y;       
}Point;

int direction(Point p0,Point p1,Point p2)
{
  return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

int distSquared(Point a,Point b)
{
  return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

int comp(Point p0,Point a, Point b)
{
  int d=direction(p0,a,b);
  if(d!=0) return (d>0);
  else return distSquared(p0,a) > distSquared(p0,b); 
}

void heapify(int l,int r, Point *P)
{
     int i,j;
     Point t;
     int isHeap;
     t=P[l];
     i=l;
     j=2*i;
     isHeap=0;
     while(j<=r && !isHeap)
     {
       if(j<r && comp(P[0],P[j],P[j+1])) 
          j++;
       if(comp(P[0],t,P[j]))
       {
            P[i]=P[j];
            i=j;
            j=2*i;
       }
       else 
            isHeap=1;
     }
     P[i]=t;
}

void buildHeap(int n,Point *P)
{
int i;
   for(i=n/2;i>=1;i--)
      heapify(i,n,P);
}

void heapSort(int n,Point *P)
{
int i;
Point t;
    buildHeap(n,P); 
    for(i=n;i>=2;i--)
    {
        t=P[1];
        P[1]=P[i];
        P[i]=t;
        heapify(1,i-1,P);
    }                 
}

int removeDuplicates(int size, Point *P)
{
int i,prev,count;
    prev=1;
    for(i=1;i<size;i++)
    {
       if(direction(P[0],P[i],P[prev])!=0)
       {
           prev++;
           P[prev]=P[i];
       }
    }
    count=prev+1;
return count;
}

void Solve(int n,Point *P, int *top, Point *S)
{
     int i,k,min,m;
     Point t;
     min=0;
     for(i=1;i<n;i++)
        if(P[i].y<P[min].y ||(P[i].y==P[min].y && P[i].x <P[min].x))
            min=i;
     t=P[0];
     P[0]=P[min];
     P[min]=t;
     heapSort(n-1,P);
     m=removeDuplicates(n,P);
     k=-1;
     i=0;
     while(i<n && i<3)
     {
        k++;
        S[k]=P[i];
        i++;
     }
     for(i=3;i<m;i++)
     {
        while(k>=1 && direction(S[k-1],S[k],P[i])<=0)
            k--;
        k++;
        S[k]=P[i];    
     }
     k++;
     S[k]=P[0];
(*top)=k;                       
}

int main()
{
 int j,k,n;
 Point *a;
 Point *b;
 FILE *in;
 FILE *out;
 
 if ((in = fopen("inputg.txt", "rt"))
       == NULL)
   {
      fprintf(stderr, "Cannot open input file.\n");
      return 1;
   }
 if ((out = fopen("outputg.txt", "wt"))
       == NULL)
   {
      fprintf(stderr, "Cannot open output file.\n");
      return 1;
   }
 while(!feof(in))
 {
   fscanf(in,"%d",&n);
   a=(Point *)malloc(n*sizeof(Point));
   b=(Point *)malloc(n*sizeof(Point));
   for(j=0;j<n;j++)
      fscanf(in,"%d %d",&a[j].x,&a[j].y);
   Solve(n,a,&k,b);
   for(j=0;j<k;j++)
      printf("%d %d \n",b[j].x,b[j].y);
   printf("\n");
   fprintf(out,"%d\n",k);
   for(j=0;j<k;j++)
      fprintf(out,"%d %d ",b[j].x,b[j].y);
   fprintf(out,"\n");
   free(a);
   free(b);
 }
 fclose(in);
 fclose(out);
 
 getch();
 return 0;
}
