#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <cassert>
#include <vector>
#include <deque>
#include <array>
using namespace std;
template<typename Iterator>
using value_type = typename iterator_traits<Iterator>::value_type;
typedef double Coord;
typedef array<Coord,2> Point;
auto cross=[](Point o,Point a,Point b)
{
return (a[0]-o[0])*(b[1]-o[1]) - (a[1]-o[1])*(b[0]-o[0]);
};
template<typename RanIt,typename InIt>
RanIt monotone_chain(InIt first_point,InIt last_point, RanIt first,RanIt last)
{
while(first_point!=last_point)
{
while
(
(last-first)>=2 &&
cross(last[-2], last[-1], *first_point)<=0
)
--last;
*last++ = *first_point++;
}
return last;
}
template<typename RanItIn,typename RanItOut>
RanItOut convex_hull(RanItIn first_point,RanItIn last_point, RanItOut first)
{
typedef reverse_iterator<RanItIn> RevIn;
if(first_point==last_point)
return first;
sort(first_point,last_point);
first = monotone_chain(first_point,last_point, first,first);
--first;
return monotone_chain(RevIn(last_point),RevIn(first_point), first,first);
}
template<typename RanIt>
vector<value_type<RanIt>> convex_hull(RanIt first_point,RanIt last_point)
{
vector<value_type<RanIt>> result(2*distance(first_point,last_point));
result.erase
(
convex_hull(first_point,last_point,begin(result)),
end(result)
);
return result;
}
ostream &operator<<(ostream &os,Point p)
{
return os << "(" << p[0] << "," << p[1] << ")";
}
int main()
{
deque<Point> input;
for(Coord i=0;i<10;++i) for(Coord j=0;j<10;++j)
input.push_front(Point{{i,j}});
for(auto p : convex_hull(begin(input),end(input)))
cout << p << endl;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8aXRlcmF0b3I+CiNpbmNsdWRlIDxvc3RyZWFtPgojaW5jbHVkZSA8Y2Fzc2VydD4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGRlcXVlPgojaW5jbHVkZSA8YXJyYXk+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGU8dHlwZW5hbWUgSXRlcmF0b3I+CnVzaW5nIHZhbHVlX3R5cGUgPSB0eXBlbmFtZSBpdGVyYXRvcl90cmFpdHM8SXRlcmF0b3I+Ojp2YWx1ZV90eXBlOwoKdHlwZWRlZiBkb3VibGUgQ29vcmQ7CnR5cGVkZWYgYXJyYXk8Q29vcmQsMj4gUG9pbnQ7CgphdXRvIGNyb3NzPVtdKFBvaW50IG8sUG9pbnQgYSxQb2ludCBiKQp7CiAgICByZXR1cm4gKGFbMF0tb1swXSkqKGJbMV0tb1sxXSkgLSAoYVsxXS1vWzFdKSooYlswXS1vWzBdKTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFJhbkl0LHR5cGVuYW1lIEluSXQ+ClJhbkl0IG1vbm90b25lX2NoYWluKEluSXQgZmlyc3RfcG9pbnQsSW5JdCBsYXN0X3BvaW50LCBSYW5JdCBmaXJzdCxSYW5JdCBsYXN0KQp7CiAgICB3aGlsZShmaXJzdF9wb2ludCE9bGFzdF9wb2ludCkKICAgIHsKICAgICAgICB3aGlsZQogICAgICAgICgKICAgICAgICAgICAgKGxhc3QtZmlyc3QpPj0yICYmCiAgICAgICAgICAgIGNyb3NzKGxhc3RbLTJdLCBsYXN0Wy0xXSwgKmZpcnN0X3BvaW50KTw9MAogICAgICAgICkKICAgICAgICAgICAgLS1sYXN0OwogICAgICAgICpsYXN0KysgPSAqZmlyc3RfcG9pbnQrKzsKICAgIH0KICAgIHJldHVybiBsYXN0Owp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBSYW5JdEluLHR5cGVuYW1lIFJhbkl0T3V0PgpSYW5JdE91dCBjb252ZXhfaHVsbChSYW5JdEluIGZpcnN0X3BvaW50LFJhbkl0SW4gbGFzdF9wb2ludCwgUmFuSXRPdXQgZmlyc3QpCnsKICAgIHR5cGVkZWYgcmV2ZXJzZV9pdGVyYXRvcjxSYW5JdEluPiBSZXZJbjsKICAgIGlmKGZpcnN0X3BvaW50PT1sYXN0X3BvaW50KQogICAgICAgIHJldHVybiBmaXJzdDsKICAgIHNvcnQoZmlyc3RfcG9pbnQsbGFzdF9wb2ludCk7CiAgICBmaXJzdCA9IG1vbm90b25lX2NoYWluKGZpcnN0X3BvaW50LGxhc3RfcG9pbnQsIGZpcnN0LGZpcnN0KTsKICAgIC0tZmlyc3Q7CiAgICByZXR1cm4gbW9ub3RvbmVfY2hhaW4oUmV2SW4obGFzdF9wb2ludCksUmV2SW4oZmlyc3RfcG9pbnQpLCBmaXJzdCxmaXJzdCk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFJhbkl0Pgp2ZWN0b3I8dmFsdWVfdHlwZTxSYW5JdD4+IGNvbnZleF9odWxsKFJhbkl0IGZpcnN0X3BvaW50LFJhbkl0IGxhc3RfcG9pbnQpCnsKICAgIHZlY3Rvcjx2YWx1ZV90eXBlPFJhbkl0Pj4gcmVzdWx0KDIqZGlzdGFuY2UoZmlyc3RfcG9pbnQsbGFzdF9wb2ludCkpOwogICAgcmVzdWx0LmVyYXNlCiAgICAoCiAgICAgICAgY29udmV4X2h1bGwoZmlyc3RfcG9pbnQsbGFzdF9wb2ludCxiZWdpbihyZXN1bHQpKSwKICAgICAgICBlbmQocmVzdWx0KQogICAgKTsKICAgIHJldHVybiByZXN1bHQ7Cn0KCm9zdHJlYW0gJm9wZXJhdG9yPDwob3N0cmVhbSAmb3MsUG9pbnQgcCkKewogICAgcmV0dXJuIG9zIDw8ICIoIiA8PCBwWzBdIDw8ICIsIiA8PCBwWzFdIDw8ICIpIjsKfQoKaW50IG1haW4oKQp7CiAgICBkZXF1ZTxQb2ludD4gaW5wdXQ7CiAgICBmb3IoQ29vcmQgaT0wO2k8MTA7KytpKSBmb3IoQ29vcmQgaj0wO2o8MTA7KytqKQogICAgICAgIGlucHV0LnB1c2hfZnJvbnQoUG9pbnR7e2ksan19KTsKICAgIGZvcihhdXRvIHAgOiBjb252ZXhfaHVsbChiZWdpbihpbnB1dCksZW5kKGlucHV0KSkpCiAgICAgICAgY291dCA8PCBwIDw8IGVuZGw7Cn0=