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: Time Limit Exceeded)

#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <algorithm>
#include <cmath>

using namespace std;

long gcd(long i, long j)
{
    if (i < j) {
        swap(i, j);
    }
    if (j == 0) {
        return i;
    }
    long k = i % j;
    return gcd(j, k);
}

int main()
{
    list<pair<pair<long, long>, double> > lzSortedPnt;
    {
        long n = 0;
        vector<pair<long, long> > vzPnt;
        {
            cin >> n;
            vzPnt.resize(n);
            long i = 0;
            for (i = 0; i < n; ++i) {
                cin >> vzPnt[i].second >> vzPnt[i].first; // y,x???????????°?????? 
            }
            sort(vzPnt.begin(), vzPnt.end()); // ?????????????????§????§????????±???????(first,second?????????????????????????????????????????????) 
            if (n < 2) { // ????????±???????????????????????? 
                cout << n << "\n";
                if (n == 1) {
                    cout << vzPnt[0].second << " " << vzPnt[0].first << "\n";
                }
                return 0;
            }
            for (i = 0; i < n; ++i) {
                swap(vzPnt[i].first, vzPnt[i].second); // ?´??????????????????§x,y????????????????????? 
            }
        }

        vector<pair<pair<double, double>, size_t> > vzValuePnt(n); // ?????¬?????????????????¢?????´??????????????????????????????????????????????????? ((?§?????????¨?????????????????????, ?????????2??????), vzPnt????????????) 
        {
            vzValuePnt[0] = pair<pair<double, double>, size_t>(pair<double, double>(0.0, 0.0), 0); // ??????????????????????????????????????????????¢??????????????????§???index0?????????????????????????????????????????? 
            long i = 1;
            for (i = 1; i < n; ++i) {
                long iX = vzPnt[i].first - vzPnt[0].first;
                long iY = vzPnt[i].second - vzPnt[0].second;
                double dLenSq = (iX * iX) + (iY + iY); // ?????????-10000???10000??¨????????????????????????????????????????????????????????????????????????????????????sqrt?????????????????????????????¨?????????????????????????????§??????0????????§?????????????????? 
                long iGcd = gcd(iX, iY); // ???????°???°???????????§ (a*Y)/(a*X) == (b*Y)/(b*X) ????????????????????????????????§?????§??¬?´???°??§?????£?????????????????????????????¨?????????????????????????????§iGcd???0????????§?????????????????? 
                iX /= iGcd;
                iY /= iGcd;
                double dAngle = 0;
                if (iX > 0) {
                    dAngle = (double)iY / iX; // 0???20000 (??§?¨??????´??°??§?????????-10000???10000??¨????????????????????????????????????????????????) 
                } else if (iX == 0) {
                    dAngle = 25000; // 25000??? iX==0 ?????±????????¨???????????¨??????????????? 
                } else {
                    dAngle = 50000 + (double)iY / iX; // 30000???50000 
                }
                vzValuePnt[i] = pair<pair<double, double>, size_t>(pair<double, double>(dAngle, dLenSq), i);
            }
            sort(vzValuePnt.begin(), vzValuePnt.end());
        }

        long i = 0;
        for (i = 0; i < n; ++i) {
            lzSortedPnt.push_back(pair<pair<long, long>, double>(vzPnt[vzValuePnt[i].second], vzValuePnt[i].first.first));
        }
    }

    list<pair<long, long> > lzResultPnt;
    {
        // ?????????2??????????????¶????§£(??\??????1?????\????????´???????????????????????±????????¨????????±??£??????????????§??????2?????\????????????) 
        lzSortedPnt.push_back(lzSortedPnt.front()); // ?????????????????????????????¨???????????¨????????? 
        lzResultPnt.push_back(lzSortedPnt.front().first);
        lzSortedPnt.pop_front();
        lzResultPnt.push_back(lzSortedPnt.front().first);
        lzSortedPnt.pop_front();
    }

    while (!lzSortedPnt.empty()) {
        list<pair<pair<long, long>, double> >::iterator it = lzSortedPnt.begin();
        vector<list<pair<pair<long, long>, double> >::iterator> vzIt;
        vzIt.push_back(it);
        ++it;
        while (it != lzSortedPnt.end()) {
            if (vzIt[0]->second != it->second) { // FIXME (double????????§?????´?????????????????§???????????????????????????????????¢????????§???????????????????????????????????§?????????????????????) 
                break;
            }
            vzIt.push_back(it);
            ++it;
        }
        if (vzIt.size() > 1) {
            // ?????£?????????????????????????±??????? 
            pair<long, long> azResultLast[2] = { *(--(--(lzResultPnt.end()))), *(--(lzResultPnt.end())) };
            double aiLastResultDirRev[2] = { azResultLast[0].first - azResultLast[1].first, azResultLast[0].second - azResultLast[1].second };
            double aiNextPntDir0[2] = { vzIt[0]->first.first - azResultLast[1].first, vzIt[0]->first.second - azResultLast[1].second };
            double aiNextPntDir1[2] = { vzIt[vzIt.size() -1]->first.first - azResultLast[1].first, vzIt[vzIt.size() -1]->first.second - azResultLast[1].second };
            double dAngle0 = atan2(aiLastResultDirRev[0] * aiNextPntDir0[1] - aiLastResultDirRev[1] * aiNextPntDir0[0], aiLastResultDirRev[0] * aiNextPntDir0[0] + aiLastResultDirRev[1] * aiNextPntDir0[1]);
            double dAngle1 = atan2(aiLastResultDirRev[0] * aiNextPntDir1[1] - aiLastResultDirRev[1] * aiNextPntDir1[0], aiLastResultDirRev[0] * aiNextPntDir1[0] + aiLastResultDirRev[1] * aiNextPntDir1[1]);
            if (dAngle0 < 0.0) {
                dAngle0 += 2.0 * 3.14159265358979; // FIXME 
            }
            if (dAngle1 < 0.0) {
                dAngle1 += 2.0 * 3.14159265358979; // FIXME 
            }
            if (dAngle0 > dAngle1) { // ???????§?????°????????????????????????????????????????????????? 
                reverse(vzIt.begin(), vzIt.end());
            }
        }
        size_t i = 0;
        for (i = 0; i < vzIt.size(); ++i) {
            while (true) {
                pair<long, long> azResultLast[2] = { *(--(--(lzResultPnt.end()))), *(--(lzResultPnt.end())) };
                long aiLastResultDir[2] = { azResultLast[1].first - azResultLast[0].first, azResultLast[1].second - azResultLast[0].second };
                long aiNextPntDir[2] = { vzIt[i]->first.first - azResultLast[1].first, vzIt[i]->first.second - azResultLast[1].second };
                {
                    // ?§?????????¶????????????????????£???????????????????????? 
                    long iSign = aiLastResultDir[0] * aiNextPntDir[1] - aiLastResultDir[1] * aiNextPntDir[0];
                    if (iSign < 0) {
                        lzResultPnt.pop_back();
                    } else {
                        break;
                    }
                }
            }
            lzResultPnt.push_back(vzIt[i]->first);
            lzSortedPnt.erase(vzIt[i]);
        }
    }

    lzResultPnt.pop_back(); // ?????????????????????????????????????????§?????? 
    long i = 0;
    size_t n = lzResultPnt.size();
    cout << n << "\n";
    list<pair<long, long> >::iterator it = lzResultPnt.begin();
    for ( ; it != lzResultPnt.end(); ++it) {
        cout << it->first << " " << it->second << "\n";
    }

    return 0;
}