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: Wrong Answer)

#define _USE_MATH_DEFINES
#include <climits>
#include<cmath>

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<utility>
#include<vector>
//#include<numeric>
int gcd(int a, int b) {
  return b ? gcd(b, a%b) : a;
}
class Points{
private:
    std::pair<int,int> nCood;//??¶?????????????¬??????§?¨?
	double dArg;//??¶?????????????§?????????¨??¶?????????????§?
    double dLength_2;//??¶?????????????§?????????¨??¶??????????????¢
public:
	Points(){
		nCood.first = nCood.second  = 0;
         dArg = dLength_2 = 0.;
	}
	void SetPoint (std::pair<int,int>& nInput){
	    nCood=nInput;  
	    return;
	}
    std::pair<int,int>nnGetCood(){
	    return nCood;
	}
	void SetArg ( Points StartPoint ){	
        
        std::pair<int,int> nnRescaledCood(nCood.first - StartPoint.nnGetCood().first,nCood.second - StartPoint.nnGetCood().second);
        int GCD = gcd(std::abs(nnRescaledCood.first),std::abs(nnRescaledCood.second));
        nnRescaledCood.first /= GCD;
        nnRescaledCood.second /= GCD;
       /*
       double dLengthVector =  std::sqrt( 1. * (nCood.first - (StartPoint.nnGetCood()).first ) 
                                * ( nCood.first - (StartPoint.nnGetCood()).first ) 
                            + ( nCood.second - (StartPoint.nnGetCood()).second ) 
                                * ( nCood.second - (StartPoint.nnGetCood() ).second) );
		double dCos = ( nCood.first - (StartPoint.nnGetCood() ).first) / dLengthVector;
       */

        double dLengthVector =  std::sqrt(1. * 
                                    (  nnRescaledCood.first  *  nnRescaledCood.first 
                                   +  nnRescaledCood.second     *  nnRescaledCood.second) );
		double dCos =  nnRescaledCood.first / dLengthVector;
		dArg=std::acos(dCos);
       
		return;
	}
    void SetLength (Points StartPoint){
        dLength_2 = (nCood.first - StartPoint.nnGetCood().first)
                    * (nCood.first - StartPoint.nnGetCood().first) 
                  + (nCood.second - StartPoint.nnGetCood().second)
                    *(nCood.second - StartPoint.nnGetCood().second);
        return;
    }
	
	double dGetArg(){
	return dArg;
	}
    double dGetLength_2(){
	return dLength_2;
    }
};

/*
*????????????????????? for dArg@points
*/
void quick_sort_part(std::vector<Points>&points,int left,int right);
std::pair<int,int> partition(std::vector<Points>&points,int left,int right);
/*
*?????????????????????for dLength@points
*nUpDown(1)??????
*nUpDown(-1)??????
**????????§????????????????¶?
*/
void quick_sort_part_2(std::vector<Points>&points,int nUpDown ,int left,int right);
int partition_2(std::vector<Points>&points,int nUpDown,int left,int right);
/*
*??????dArg??????????????????????????????????????????????????????
*???????????¶?????????????§???????points[0]??????????????¢??§?±??????????
*??¶??????points[0]->[1]??¨??????????????????
*???????????????????????????????????????
*/
void judgeIsometric(std::vector<Points>&points);
/*
*??????????¬?????????£(true)??????????????§???i???????????¶?????????????????????????????????
*points[1]??¨[points.size()-1]???????????????
*1<=i<=points.size()-2?????????????????????
*/
bool bCrossProduct (Points &points, std::vector<std::pair<int,int> >& StackPoints,int i);
bool bIsPararell(std::vector<Points>&points,int nI,int nJ);
int main(void){
   
	int nInput;
    scanf("%d",&nInput );
	
	std::vector<Points> aComp_nPoints(nInput);///////??¶???????????????????????????????????£????????????
    std::pair<int,int> prnnInput;
	int nMinX = INT_MAX,nMinY = INT_MAX;
	int nIndexMin;
    
    for (int i = 0;i< nInput;++i){
    
        scanf("%d%d",&(prnnInput.first),&(prnnInput.second) );
		aComp_nPoints[i].SetPoint(prnnInput);
			
            if (nMinY == prnnInput.second && nMinX > prnnInput.first){
                nMinX = prnnInput.first;
                nIndexMin = i;
            }
            else if (nMinY > prnnInput.second){
				nMinY = prnnInput.second;
                nMinX = prnnInput.first;
                nIndexMin = i;
            
			}
            
	}
	/*
	*??¶??????????????§y???????°??????§????????????????????§?????????x????°???????????????¢???
	*/
	
	std::swap(aComp_nPoints[0],aComp_nPoints[nIndexMin]);
	
	/*
	*aComp_nPoints[0]????????????????§?????±????????°?????????????aComp_nPoints[i>0]?????????????????????
    *????§??????????aComp_nPoints[0]??¨????????¢????±?????????????????????????
	*/
	for(int i = 1;i < nInput;++i){
		aComp_nPoints[i].SetArg ( aComp_nPoints[0] );
	}
    quick_sort_part(aComp_nPoints,0,aComp_nPoints.size()-1);    
    judgeIsometric (aComp_nPoints);  
   /*
   *????????¨?????????????????????pnnPrintPoints?????\?????????
   **?????????????????????????????¶????????¨??????????´?????¢?????????????????????§?????¢??????????§???£???
   */
    std::vector<std::pair<int,int> > pnnPrintPoints(aComp_nPoints.size());
    pnnPrintPoints[0]=aComp_nPoints[0].nnGetCood();
    int iIndex=0;
    for (int i = 1; i <aComp_nPoints.size()-1 ; ++i){
        pnnPrintPoints[++iIndex] = aComp_nPoints[i].nnGetCood();

         while (!bCrossProduct (aComp_nPoints[i+1],pnnPrintPoints,iIndex)){
             --iIndex  ;
        }
       
    }
    pnnPrintPoints[++iIndex] = aComp_nPoints[aComp_nPoints.size()-1].nnGetCood();
    
     
    printf("%d\n",++iIndex);//++??¢???????????????=????´???°

    
    for (int i = 0 ;i < iIndex; ++i){
        printf("%d %d\n",pnnPrintPoints[i].first,pnnPrintPoints[i].second);
    }
  // system ("pause");
	return 0;
}
std::pair<int,int> partition (std::vector<Points>&points,int left,int right){
   
    double dValue = points[right].dGetArg();
std::pair<int,int> ipairIndex(left-1,left-1);

  /*
  *dValue????????§??????????????\?????????????????????ipairIndex.second???
  */
    for (int j = left;j <= right-1;++j){
        if(points[j].dGetArg() <= dValue){        
        ++ipairIndex.second;
        std::swap(points[ipairIndex.second],points[j]);
        }
    }
    std::swap(points[ipairIndex.second+1],points[right]);
     ++ipairIndex.second;
  /*
  *dValue???????°???????????????\????????????????????????ipairIndex.first
  */  
     

        
        
     for (int j = left;j < ipairIndex.second;++j){
   
        if(points[j].dGetArg()<dValue -1.e-7){               
      ++ipairIndex.first;   
            std::swap(points[ipairIndex.first],points[j]);
        
        }
    }
      
   
  return ipairIndex;
}
void quick_sort_part (std::vector<Points>&points,int left,int right){
    if (left < right){
        int nmiddleValue=points[right].dGetArg();
        
        std::pair<int,int> nMiddleIndex = partition(points, left, right);
        if(nMiddleIndex.first <= nMiddleIndex.second ) {
            quick_sort_part ( points, left, nMiddleIndex.first );
            quick_sort_part ( points, nMiddleIndex.second+1 , right);
        }
      
    }

    return;   
}
int partition_2 (std::vector<Points>&points,int nUpDown,int left,int right){
    
    double dValue = points[right].dGetLength_2();
    int iIndex = left-1;
    for (int j = left;j <= right-1;++j){
        if (nUpDown == 1 && points[j].dGetLength_2() <= dValue){
        ++iIndex;
        std::swap (points[iIndex],points[j]);
        }
        else  if (nUpDown == -1 && points[j].dGetLength_2() >= dValue){
        ++iIndex;
        std::swap (points[iIndex],points[j]);
        }
    }
    std::swap (points[iIndex+1],points[right]);
        return iIndex+1;
}
void quick_sort_part_2 (std::vector<Points>&points,int nUpDown,int left,int right){
    if (left < right){
        int nMiddleIndex = partition_2(points,nUpDown, left, right);
        quick_sort_part_2 ( points,nUpDown, left, nMiddleIndex - 1);
        quick_sort_part_2 ( points,nUpDown, nMiddleIndex + 1, right);
    }

    return;   
}
void judgeIsometric (std::vector<Points>&points){
    points[points.size() - 1].SetLength(points[0]);
    int iLeft=1,iRight=1;
    for (int i = 1 ; i < points.size() - 1 ; ++i){
        if (bIsPararell (points,i,i+1)){
            iRight=i+1;
            if(!points[i].dGetLength_2()){
                points[i].SetLength(points[0]);          
            }
            points[i+1].SetLength(points[0]);
               if (iRight == points.size() - 1){
                quick_sort_part_2 (points,-1,iLeft,iRight);
                }
            }
        else{
            if (iLeft != iRight){
                if (iLeft==1){
                quick_sort_part_2 (points,1,iLeft,iRight);
                }
              
                else{
                quick_sort_part_2 (points,-1,iLeft,iRight);
                points.erase(points.begin() + iLeft + 1,points.begin() +iRight );
                }
            }
            iLeft = iRight =i+1;
        }
    }    
    return;
}
bool bIsPararell(std::vector<Points>&points,int nI,int nJ){
  int nPararellCriterion =   (points[nI].nnGetCood().first - points[0].nnGetCood().first) * (points[nJ].nnGetCood().second - points[0].nnGetCood().second)
                           -(points[nJ].nnGetCood().first - points[0].nnGetCood().first) * (points[nI].nnGetCood().second - points[0].nnGetCood().second);
  return nPararellCriterion == 0;
}
bool bCrossProduct (Points &points, std::vector<std::pair<int,int> >& StackPoints,int i){
       
  
    double dValueCrossPro;
   
        dValueCrossPro = 
            (StackPoints[i].first - StackPoints[i-1].first) 
                * (points.nnGetCood().second - StackPoints[i].second)
            -(StackPoints[i].second - StackPoints[i-1].second) 
                * (points.nnGetCood().first - StackPoints[i].first) ;
        return dValueCrossPro >= 0;
     
}