#define PROBLEM "https://judge.yosupo.jp/problem/static_convex_hull"
// Include geometry first to check that support does not depend on include order.#include"../../geometry/all.hpp"
#include"../../math/rational.hpp"
#include"../../math/matrix/linear_algebra.hpp"
#include"../../utilities/bigint.hpp"
#include"../../utilities/fast_io.hpp"#include<algorithm>
#include<cassert>
#include<cmath>
#include<cstdint>
#include<string>
#include<type_traits>
#include<utility>
#include<vector>namespace{usingnamespacem1une::geometry;usingFraction=m1une::math::Rational<>;usingBigInt=m1une::utilities::BigInt;usingBigFraction=m1une::math::Rational<BigInt>;static_assert(Coordinate<Fraction>&&ExactCoordinate<Fraction>);static_assert(Coordinate<BigFraction>&&ExactCoordinate<BigFraction>);static_assert(!Coordinate<bool>&&!Coordinate<std::string>);static_assert(!ExactCoordinate<double>);static_assert(std::same_as<wide_type<Fraction>,Fraction>);static_assert(std::same_as<wide_type<BigFraction>,BigFraction>);static_assert(std::same_as<wide_type<longlong>,__int128_t>);static_assert(std::same_as<wide_type<float>,longdouble>);static_assert(std::same_as<std::common_type_t<Fraction,int>,Fraction>);static_assert(std::same_as<std::common_type_t<Fraction,double>,longdouble>);static_assert(std::same_as<std::common_type_t<float,BigFraction>,longdouble>);static_assert(!std::convertible_to<Fraction,double>);static_assert(static_cast<float>(Fraction(1,2))==0.5F);static_assert(static_cast<double>(Fraction(1,2))==0.5);static_assert(orientation(Point<Fraction>(0,0),Point<Fraction>(1,0),Point<Fraction>(0,Fraction(1,1000000000000000LL)))==1);template<classR>voidfixed_test(){usingP=Point<R>;constPorigin;constPhalf(R(1,2),R(1,2));assert(dot(half,half)==R(1,2));assert(cross(P(R(1,2),0),P(0,R(1,3)))==R(1,6));assert(distance2(origin,half)==R(1,2));assert(half*2==P(1,1));assert(2*half==P(1,1));assert(half/2==P(R(1,4),R(1,4)));assert(half*R(2,3)==P(R(1,3),R(1,3)));assert(R(2,3)*half==P(R(1,3),R(1,3)));assert(half/R(2,3)==P(R(3,4),R(3,4)));assert((half*0.5L==Point<longdouble>(0.25L,0.25L)));assert((Point<int>(1,2)*R(1,2)==P(R(1,2),1)));assert((Point<float>(half)==Point<float>(0.5F,0.5F)));assert((Point<double>(half)==Point<double>(0.5,0.5)));assert((internal_division_point(origin,P(1,1),R(1,2),R(1,2))==Point<longdouble>(0.5L,0.5L)));assert((external_division_point(origin,P(1,1),R(1,2),R(1,4))==Point<longdouble>(2,2)));constSegment<R>singleton{half,half};assert(on_segment(singleton,half));assert(!on_segment(singleton,half+P(R(1,1000000),0),1));constSegment<R>diagonal{origin,P(1,1)};constSegment<R>other{P(0,1),P(1,0)};assert(intersects(diagonal,other));assert(linear_intersection(diagonal,other).kind==LinearIntersectionKind::Point);constRay<R>ray{origin,half};assert(on_ray(ray,P(1,1))&&!on_ray(ray,P(-1,-1)));assert(intersects(ray,other));constLine<R>horizontal{origin,P(1,0)};constLine<R>vertical{origin,P(0,1)};assert(orthogonal(horizontal,vertical));assert(parallel(horizontal,Line<R>{P(0,1),P(1,1)}));constLine<R>bisector=perpendicular_bisector(origin,P(1,0));assert(on_line(bisector,P(R(1,2),0)));assert(on_line(bisector,half));conststd::vector<P>square{origin,P(1,0),P(1,1),P(0,1)};conststd::vector<P>points{origin,P(1,0),P(1,1),P(0,1),half};assert(convex_hull(points)==square);assert(polygon_area2(square)==2);assert(point_in_polygon(square,half)==PointInPolygon::Inside);constConvexPolygon<R>polygon(square);assert(polygon.contains(half)==PointInPolygon::Inside);assert(convex_layers(points)==std::vector<int>({1,1,1,1,2}));assert(minkowski_sum(square,square).size()==4);assert(convex_decomposition(square)->size()==1);assert(steiner_convex_decomposition(square)->size()==1);conststd::vector<P>concave{origin,P(1,0),P(1,R(1,2)),P(R(1,2),R(1,2)),P(R(1,2),1),P(0,1)};constautominimum_decomposition=minimum_convex_decomposition(concave);assert(minimum_decomposition.has_value()&&minimum_decomposition->size()==2);Rtotal_area=0;for(constauto&piece:*minimum_decomposition){assert(is_convex_polygon(piece));total_area+=polygon_area2(piece);}assert(total_area==polygon_area2(concave));constCountPointsInTriangle<R>counter(square,std::vector<P>{P(R(3,4),R(1,4))});assert(counter.query(0,1,2)==1);assert(manhattan_mst(square).cost==3);assert(euclidean_mst(square).cost==3);assert(delaunay_triangulation(square).triangles.size()==2);assert(voronoi_diagram(square).edges.size()>0);assert(minimum_enclosing_circle(square)->support.size()==2);std::vector<P>fractional_square=square;for(P&point:fractional_square)point=point/R(3);assert(manhattan_mst(fractional_square).cost==1);assert(std::fabs(euclidean_mst(fractional_square).cost-1)<1e-12L);assert(delaunay_triangulation(fractional_square).triangles.size()==2);assert(!voronoi_diagram(fractional_square).edges.empty());conststd::vector<Segment<R>>segments{Segment<R>{P(R(1,2),0),P(R(1,2),1)},Segment<R>{P(0,R(1,2)),P(1,R(1,2))}};assert(manhattan_segment_intersections(segments)==1);assert(manhattan_segment_intersection_points(segments)==std::vector<P>{half});conststd::vector<AxisAlignedRectangle<R>>rectangles{AxisAlignedRectangle<R>(0,R(1,2),0,1),AxisAlignedRectangle<R>(R(1,4),1,0,1)};assert(rectangle_union_area(rectangles)==1);constCircle<R>circle{origin,R(1,2)};assert(point_in_circle(circle,P(R(1,2),0))==PointInCircle::Boundary);assert(point_in_circle(circle,P(R(1,2)+R(1,1000000),0),1)==PointInCircle::Outside);assert(on_circle(circle,P(R(1,2),0)));assert(on_circle(circle,Point<int>(0,0))==false);assert(circle_relation(circle,Circle<R>{P(1,0),R(1,2)})==CircleRelation::ExternallyTangent);assert(intersects(circle,circle));m1une::matrix::Matrix<R>matrix(2,2);matrix[0][0]=R(1,2);matrix[0][1]=R(1,3);matrix[1][0]=1;matrix[1][1]=-1;constautoinverse=m1une::matrix::inverse(matrix);assert(inverse.has_value());assert(matrix**inverse==m1une::matrix::Matrix<R>::identity(2));}// Gift wrapping is an independent quadratic hull oracle on scaled integers.std::vector<Point<longlong>>naive_hull(std::vector<Point<longlong>>points){std::sort(points.begin(),points.end());points.erase(std::unique(points.begin(),points.end()),points.end());if(points.size()<2)returnpoints;std::vector<Point<longlong>>hull;intcurrent=0;do{hull.push_back(points[current]);intnext=(current+1)%int(points.size());for(inti=0;i<int(points.size());++i){constautoturn=cross(points[current],points[next],points[i]);if(turn<0||(turn==0&&distance2(points[current],points[next])<distance2(points[current],points[i])))next=i;}current=next;}while(current!=0);returnhull;}template<classR>voidrandomized_test(inttrials){usingP=Point<R>;std::uint64_tstate=1307;autorandom=[&state](){state^=state<<7;state^=state>>9;returnstate;};for(inttrial=0;trial<trials;++trial){std::vector<P>points;std::vector<Point<longlong>>scaled;constintsize=int(random()%20);for(inti=0;i<size;++i){constlonglongx=static_cast<longlong>(random()%41)-20;constlonglongy=static_cast<longlong>(random()%41)-20;constintdx=1+int(random()%5),dy=1+int(random()%5);points.emplace_back(R(x,dx),R(y,dy));scaled.emplace_back(x*(60/dx),y*(60/dy));}constautoexpected_hull=naive_hull(scaled);constautohull=convex_hull(points);assert(hull.size()==expected_hull.size());for(std::size_ti=0;i<hull.size();++i){assert(hull[i].x*60==expected_hull[i].x);assert(hull[i].y*60==expected_hull[i].y);}constautonearest=closest_pair(points);constautofarthest=farthest_pair(points);assert(nearest.has_value()==(size>=2));assert(farthest.has_value()==(size>=2));if(size>=2){autominimum=distance2(scaled[0],scaled[1]);automaximum=minimum;std::pair<int,int>nearest_indices(0,1);for(inti=0;i<size;++i){for(intj=i+1;j<size;++j){constautosquared=distance2(scaled[i],scaled[j]);if(squared<minimum){minimum=squared;nearest_indices=std::pair(i,j);}maximum=std::max(maximum,squared);}}assert(nearest->distance_squared*3600==static_cast<longlong>(minimum));assert(std::pair(nearest->first,nearest->second)==nearest_indices);assert(farthest->distance_squared*3600==static_cast<longlong>(maximum));}if(size>=3){assert(orientation(points[0],points[1],points[2],1)==orientation(scaled[0],scaled[1],scaled[2]));}}}voidbigint_precision_test(){constBigIntpower("1000000000000000000000000000000000000000000000000000000000000");constBigFractionbase(power);constBigFractiontiny(1,power);usingP=Point<BigFraction>;constPa(base,base),b(base+1,base),c(base,base+tiny);assert(cross(a,b,c)==tiny);assert(orientation(a,b,c)==1);assert(convex_hull(std::vector<P>{a,b,c}).size()==3);assert(sign<BigFraction>(tiny,1)==1);constSegment<BigFraction>singleton{a,a};assert(!on_segment(singleton,c));constCircle<BigFraction>circle{P(),1};assert(!on_circle(circle,P(1+tiny,0)));assert(point_in_circle(circle,P(1+tiny,0))==PointInCircle::Outside);assert(static_cast<float>(BigFraction(1,2))==0.5F);assert(static_cast<double>(BigFraction(1,2))==0.5);}}// namespaceintmain(){fixed_test<Fraction>();fixed_test<BigFraction>();randomized_test<Fraction>(1000);randomized_test<BigFraction>(100);bigint_precision_test();m1une::utilities::FastInputinput;m1une::utilities::FastOutputoutput;inttest_count;input>>test_count;while(test_count--){intsize;input>>size;std::vector<Point<Fraction>>points;points.reserve(size);for(inti=0;i<size;++i){longlongx,y;input>>x>>y;points.emplace_back(Fraction(x,2),Fraction(y,2));}constautohull=convex_hull(std::move(points));output<<hull.size()<<'\n';for(constauto&point:hull){output<<(point.x*2).numerator()<<' '<<(point.y*2).numerator()<<'\n';}}}
Traceback(mostrecentcalllast):File"/home/runner/.local/lib/python3.12/site-packages/onlinejudge_verify/documentation/build.py",line71,in_render_source_code_statbundled_code=language.bundle(stat.path,basedir=basedir,options={'include_paths':[basedir]}).decode()^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File"/home/runner/.local/lib/python3.12/site-packages/onlinejudge_verify/languages/cplusplus.py",line187,inbundlebundler.update(path)File"/home/runner/.local/lib/python3.12/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py",line401,inupdateself.update(self._resolve(pathlib.Path(included),included_from=path))File"/home/runner/.local/lib/python3.12/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py",line401,inupdateself.update(self._resolve(pathlib.Path(included),included_from=path))File"/home/runner/.local/lib/python3.12/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py",line400,inupdateraiseBundleErrorAt(path,i+1,"unable to process #include in #if / #ifdef / #ifndef other than include guards")onlinejudge_verify.languages.cplusplus_bundle.BundleErrorAt:geometry/lattice_point_count.hpp:line28:unabletoprocess#includein#if/#ifdef/#ifndefotherthanincludeguards