#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8,pi=acos(-1.0);
const int N=100005;
inline int dcmp(double x){return (x<-eps)?-1:(x>eps)?1:0;}//判断正负
inline double dabs(double x){return x*dcmp(x);}//绝对值
/*向量(点)*/
struct vec{double x,y;vec(double _x=0,double _y=0){x=_x;y=_y;}};
inline bool cmp_vec(vec a,vec b){return (a.x!=b.x)?a.x<b.x:a.y<b.y;}
inline double len(vec a){return sqrt(a.x*a.x+a.y*a.y);}//模长
inline double ang(vec a){return atan2(a.y,a.x);}//角度
inline vec operator +(const vec &a,const vec &b){return vec(a.x+b.x,a.y+b.y);}
inline vec operator -(const vec &a,const vec &b){return vec(a.x-b.x,a.y-b.y);}
inline vec operator *(const vec &a,const double &b){return vec(a.x*b,a.y*b);}
inline vec operator /(const vec &a,const double &b){return vec(a.x/b,a.y/b);}
inline double operator *(const vec &a,const vec &b){return a.x*b.x+a.y*b.y;}//点积
inline double operator ^(const vec &a,const vec &b){return a.x*b.y-a.y*b.x;}//叉积
inline vec rot(vec a,double the){return vec(a.x*cos(the)-a.y*sin(the),a.x*sin(the)+a.y*cos(the));}//旋转
inline vec rot90(vec a){return vec(a.y,-a.x);}//特殊角旋转
inline vec rotpt(vec a,vec b,double the){return b+rot(a-b,the);}//a绕b旋转
/*线*/
struct line{vec s,t;line(vec _s=vec(0,0),vec _t=vec(0,0)){s=_s;t=_t;}};//线
inline double maxx(line l){return max(l.s.x,l.t.x);}//大x
inline double maxy(line l){return max(l.s.y,l.t.y);}//大y
inline double minx(line l){return min(l.s.x,l.t.x);}//小x
inline double miny(line l){return min(l.s.y,l.t.y);}//小y
inline double ang(line l){return ang(l.t-l.s);}//角度
inline bool operator <(line &a,line &b){double a1=ang(a.t-a.s),a2=ang(b.t-b.s);return (dcmp(a2-a1))?a2>a1:dcmp((a.t-a.s)^(b.t-b.s))<0;}
inline bool operator ==(vec &a,vec &b){return (!dcmp(a.x-b.x)&&!dcmp(a.y-b.y));}//点是否相等
inline double dis(vec a,vec b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}//点距离
inline bool pd_pl(vec a,line b){return !dcmp((a-b.s)^(b.t-b.s));}//点是否在直线上
inline bool pd_px(vec a,line b){return pd_pl(a,b)&&(dcmp((a-b.s)*(a-b.t))<=0);}//点是否在线段上
inline vec footpt(vec a,line b){vec x=a-b.s,y=a-b.t,z=b.t-b.s;double s1=x*z,s2=-1.0*(y*z);return b.s+z*(s1/(s1+s2));}//求垂足(分别求as,at关于st的投影)
inline vec mirror(vec a,line b){return a+(footpt(a,b)-a)*2.0;}//a关于b的对称点
inline double dis_pl(vec a,line b){return dabs((a-b.s)^(a-b.t))/len(b.t-b.s);}//求a到直线b的距离(面积除以底边长)
inline double dis_px(vec a,line b){return (dcmp((a-b.s)*(b.t-b.s))<0)?len(a-b.s):(dcmp((a-b.t)*(b.t-b.s))>0)?len(a-b.t):dis_pl(a,b);}//求a到线段b的距离
inline vec pt_px(vec a,line b){return (dcmp((a-b.s)*(b.t-b.s))<0)?b.s:(dcmp((a-b.t)*(b.t-b.s))>0)?b.t:footpt(a,b);}//在线段b上与a最近的点
inline vec cross(line a,line b){vec x=a.t-a.s,y=b.t-b.s,z=a.s-b.s;return a.s+x*((y^z)/(x^y));}//求a与b的交点
inline bool pd_cross_lx(line a,line b){return (!dcmp((a.t-a.s)^(b.t-b.s)))?0:pd_px(cross(a,b),a);}//线段a与直线b是否相交
inline bool pd_cross_xx(line a,line b){return pd_cross_lx(a,b)&&pd_cross_lx(b,a);}//判断线段a是否与线段b相交
inline bool pd_cross_xx_(line a,line b)//判断两线段是否相交 (另一种方法,是否跨立)
{
if(maxx(a)<minx(b)||maxy(a)<miny(b)) return false;
if(maxx(b)<minx(a)||maxy(b)<miny(a)) return false;
double s1=(a.t-a.s)^(b.s-a.s),s2=(a.t-a.s)^(b.t-a.s);
double s3=(b.t-b.s)^(a.s-b.s),s4=(b.t-b.s)^(a.t-b.s);
return dcmp(s1)*dcmp(s2)<=0&&dcmp(s3)*dcmp(s4)<=0;//a的端点在b的两侧且b的端点在a的两侧
}
inline double s_t(vec a,vec b,vec c){return dabs((b-a)*(c-a))/2;}//已知三点求三角形面积
/*多边形*/
struct pol
{
vector<vec> pt;
inline vec& operator [](int x){return pt[x];}
inline int ne(int x){return (x<pt.size()-1)?x+1:0;}
inline void insert(vec p){pt.push_back(p);}
inline void clear(){pt.clear();}
inline int include(vec p)//点在多边形外:0,在多边形内:1,在多边形边上:2
{
int cnt=0;
for(int i=0;i<pt.size();i++)//射线法判断,射线方向为x轴正方向
{
vec s=pt[i],t=pt[ne(i)];line l=line(s,t);
if(pd_px(p,l)) return 2;
if(dcmp(p.y-miny(l))>=0&&dcmp(maxy(l)-p.y)>0)
if(dcmp(s.x+((p.y-s.y)/(t.y-s.y)*(t.x-s.x))-p.x)>0) cnt++;
}
return cnt&1;//偶数个交点则在多边形外,奇数个交点则在多边形内
}
inline double s_p()//多边形面积
{
double ans=0;
for(int i=1;i<pt.size()-1;i++) ans+=(pt[i]-pt[0])^(pt[ne(i)]-pt[0]);
return dabs(ans)/2;
}
inline double c_p()//多边形周长
{
double ans=0;
for(int i=0;i<pt.size();i++) ans+=dis(pt[i],pt[ne(i)]);
return ans;
}
inline bool pd_l(vec x,vec l,vec r){return dcmp((l-x)^(r-x))<=0;}//xl是否在xr的左侧
inline int include_(vec p)//二分法判断点是否在多边形内
{
int n=pt.size();
if(!pd_l(pt[0],p,pt[1])) return 0;
if(!pd_l(pt[0],pt[n-1],p)) return 0;
if(pd_px(p,line(pt[0],pt[1]))) return 2;
if(pd_px(p,line(pt[0],pt[n-1]))) return 2;
int l=1,r=n-2,ans=1,mid;
while(l<=r)//二分找到最接近线(pt[0],p)的(pt[0],pt[ans])
{
mid=l+r>>1;
if(!pd_l(pt[0],pt[mid],p)) l=mid+1,ans=mid;
else r=mid-1;
}
if(!pd_l(pt[ans],p,pt[ne(ans)])) return 0;
if(pd_px(p,line(pt[ans],pt[ne(ans)]))) return 2;
return 1;
}
};
/*凸包*/
inline void andrew(pol &p)
{
vector<vec>q(p.pt.size()<<1);int top=0,n=p.pt.size();
sort(p.pt.begin(),p.pt.end(),cmp_vec),q[top]=p[0];
for(int i=1;i<n;i++)
{
while(top&&dcmp((q[top-1]-q[top])^(q[top-1]-p[i]))<=0) top--;
q[++top]=p[i];
}
int tot=top;
for(int i=n-2;i>=0;i--)
{
while(top>tot&&dcmp((q[top-1]-q[top])^(q[top-1]-p[i]))<=0) top--;
q[++top]=p[i];
}
if(n>1) top--;
p.clear();
for(int i=0;i<=top;i++) p.insert(q[i]);
}
/*旋转卡壳*/
inline double diam(pol p)
{
int n=p.pt.size();double ans=0;
for(int i=0,j=1;i<n;i++)
{
for(;;j=p.ne(j)) if(dcmp(s_t(p[j],p[i],p[p.ne(i)])-s_t(p[p.ne(j)],p[i],p[p.ne(i)]))>=0) break;
ans=max(ans,max(dis(p[j],p[i]),dis(p[j],p[p.ne(i)])));
}
return ans;
}```