Problem:
Convex Cut
As shown in the figure above, cut a convex polygon
g
by a line
p1p2
and print the area of the cut polygon which is on the left-hand side of the line.
g
is represented by a sequence of points
p
1
,
p
2
,...,
p
n
where line segments connecting
p
i
and
p
i+1
(1 ≤
i
≤
n−1
) are sides of the convex polygon. The line segment connecting
p
n
and
p
1
is also a side of the polygon.
Input
The input is given in the following format:
g
(the sequence of the points of the polygon)
q
(the number of queries = the number of target lines)
1st query
2nd query
:
q
th query
g
is given as a sequence of points
p
1
,...,
p
n
in the following format:
n
x
1
y
1
x
2
y
2
:
x
n
y
n
The first integer
n
is the number of points. The coordinate of the
i
-th point
p
i
is given by two integers
x
i
and
y
i
. The coordinates of points are given in the order of counter-clockwise visit of them. Note that all interior angles of given convex polygons are less than or equal to 180.
For each query, a line represented by two points
p1
and
p2
is given. The coordinates of the points are given by four integers
p1x
,
p1y
,
p2x
and
p2y
.
Output
For each query, print the area of the cut polygon. The output values should be in a decimal fraction with an error less than 0.00001.
Constraints
3 ≤
n
≤ 100
1 ≤
q
≤ 100
-10000 ≤
x
i
,
y
i
≤ 10000
-10000 ≤
p1x
,
p1y
,
p2x
,
p2y
≤ 10000
No point in
g
will occur more than once.
p1
≠
p2
Sample Input
4
1 1
4 1
4 3
1 3
2
2 0 2 4
2 4 2 0
Sample Output
2.00000000
4.00000000

Submitted solutions:

code_snippet: //my geometry template

#include<bits/stdc++.h>
//#define double long double
using namespace std;
double const INF=1e20;
int const N=233333;
double const PI=acos(-1.0),EPS=1e-10;
int les(double x,double y){
	return x<y-EPS;
}
int leq(double x,double y){
	return x<=y+EPS;
}
int equ(double x,double y){
	return leq(x,y)&&leq(y,x);
}
double dtor(double deg){
	return deg/180.0*PI;
}
double rtod(double rad){
	return rad/PI*180.0;
}
namespace twodgeo{
	struct point{
		double x,y;
		point(double a=0.0,double b=0.0):x(a),y(b){}
		point operator+(const point&rhs)const{
			return point(x+rhs.x,y+rhs.y);
		}
		point operator-(const point&rhs)const{
			return point(x-rhs.x,y-rhs.y);
		}
		point operator*(const double&rhs)const{
			return point(x*rhs,y*rhs);
		}
		point operator/(const double&rhs)const{
			return point(x/rhs,y/rhs);
		}
		int operator<(const point&rhs)const{
			return les(x,rhs.x)||(equ(x,rhs.x)&&les(y,rhs.y));
		}
		int operator==(const point&rhs)const{
			return equ(x,rhs.x)&&equ(y,rhs.y);
		}
		double len(){
			return sqrtl(x*x+y*y);
		}
		double ang(){
			return atan2(y,x);
		}
	};
	typedef point vect;
	double dot(vect a,vect b){
		return a.x*b.x+a.y*b.y;
	}
	double ang(vect a,vect b){
		return acos(dot(a,b)/a.len()/b.len());
	}
	double cross(vect a,vect b){
		return a.x*b.y-a.y*b.x;
	}
	double triarea(point a,point b,point c){
		return cross(b-a,c-a)/2.0;
	}
	vect rotate(vect a,double rad){
		return vect(a.x*cos(rad)-a.y*sin(rad),
			a.x*sin(rad)+a.y*cos(rad));
	}
	vect normal(vect a){
		return vect(-a.y/a.len(),a.x/a.len());
	}
	vect unit(vect a){
		return vect(a.x/a.len(),a.y/a.len());
	} 
	int atinf(point a){
		return equ(abs(a.x),INF)||equ(abs(a.y),INF);
	}
	
	struct line{
		point p;
		vect v;
		line(point a={0,0},vect b={0,0}):p(a),v(b){}
		double ang(){
			return atan2(v.y,v.x);
		}
	};
	typedef line segment;
	segment makeseg(point a,point b){
		return line(a,b-a);
	}
	line midline(segment a){
		point x=a.p,y=a.p+a.v;
		return line((x+y)/2.0,normal(a.v));
	}
	point lineintersect(line a,line b){
		return a.p+a.v*(cross(b.v,a.p-b.p)/cross(a.v,b.v));
	}
	int islinepara(line a,line b){
		return equ(cross(a.v,b.v),0);
	}
	double distoline(line a,point b){
		return fabs(cross(a.v,b-a.p))/a.v.len();
	}
	double distoseg(segment a,point p){
		point x=a.p,y=a.p+a.v;
		if(x==y)
			return (p-x).len();
		vect v2=p-x,v3=p-y;
		if(les(dot(a.v,v2),0.0))
			return v2.len();
		if(les(0.0,dot(a.v,v3)))
			return v3.len();
		return distoline(a,p);
	}
	point lineproj(line a,point b){
		point x=a.p;
		vect v=a.v;
		return x+v*(dot(v,b-x)/dot(v,v));
	}
	int issegintersect(segment a,segment b){
		point a1=a.p,a2=a.p+a.v,b1=b.p,b2=b.p+b.v;
		double c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1),
		       c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1);
		return les(c1*c2,0.0)&&les(c3*c4,0.0);
	}
	int onseg(segment a,point p){
		point x=a.p,y=a.p+a.v;
		return equ(cross(x-p,y-p),0.0)&&les(dot(x-p,y-p),0.0);
	}
	
	typedef vector<line> pslg;
	typedef vector<point> polygon;
	polygon const polyplane=
		{{-INF,-INF},{-INF,INF},{INF,INF},{INF,-INF}};
	pslg const pslgplane=
		{{{-INF,-INF},{0,2*INF}},{{-INF,INF},{2*INF,0}},
		{{INF,INF},{0,2*-INF}},{{INF,-INF},{2*-INF,0}}};
	double polygonarea(polygon a){
		double s=0;
		for(int i=1;i<(int)a.size()-1;i++)
			s+=triarea(a[0],a[i],a[i+1]);
		return s;
	}
#define nxt(b,x) ((x+1)%b.size())
	int ispointinpoly(polygon a,point p){
		int cnt=0;
		for(int i=0;i<(int)a.size();i++){
			int j=nxt(a,i);
			if(onseg(makeseg(a[i],a[j]),p))
				return -1;
			double k=cross(a[j]-a[i],p-a[i]),
				d1=a[i].y-p.y,d2=a[j].y-p.y;
			if(les(0,k)&&leq(d1,0)&&les(0,d2))
				cnt++;
			if(les(k,0)&&leq(d2,0)&&les(0,d1))
				cnt--;
		}
		return !!cnt;
	}
	double convexhull(polygon a,polygon&b){
		sort(a.begin(),a.end());
		a.erase(unique(a.begin(),a.end()),a.end());
		b.clear();
#define p (int)b.size()
		for(int i=0;i<(int)a.size();i++){
			while(p>1&&leq(cross(b[p-1]-b[p-2],a[i]-b[p-2]),0))
				b.pop_back();
			b.push_back(a[i]);
		}
		for(int t=p,i=a.size()-2;~i;i--){
			while(p>t&&leq(cross(b[p-1]-b[p-2],a[i]-b[p-2]),0))
				b.pop_back();
			b.push_back(a[i]);
		}
		if(a.size()>1)
			b.pop_back();
		double res=0;
		for(int i=0;i<p;i++)
			res+=(b[i]-b[nxt(b,i)]).len();
#undef p
		return res;
	}
	double convpolydia(polygon a){
		if(a.size()==2)
			return (a[0]-a[1]).len();
		double ans=0;
		for(int i=1,j=2;i<(int)a.size();i++){
			while(leq(triarea(a[i-1],a[i],a[j]),
				triarea(a[i-1],a[i],a[nxt(a,j)])))
				j=nxt(a,j);
			ans=max(ans,max((a[i-1]-a[j]).len(),
				(a[i]-a[j]).len()));
		}
		return ans;
	}
	int onright(line a,point b){
		return les(cross(a.v,b-a.p),0);
	}
	void polytopslg(polygon a,pslg&b){
		b.push_back(makeseg(a[a.size()-1],a[0]));
		for(int i=1;i<(int)a.size();i++)
			b.push_back(makeseg(a[i-1],a[i]));
	}
	int hfplintersect(pslg a,polygon&b){
		sort(a.begin(),a.end(),[](line x,line y){
			return les(x.ang(),y.ang());
		});
		int l=0,r=0;
		pslg q;q.resize(N);
		polygon p;p.resize(N);
		q[0]=a[0];
		for(int i=1;i<(int)a.size();i++){
			while(l<r&&onright(a[i],p[r]))r--;
			while(l<r&&onright(a[i],p[l+1]))l++;
			q[++r]=a[i];
			if(l<r&&islinepara(q[r],q[r-1])){
				if(onright(q[r],q[r-1].p)&&
					les(dot(q[r].v,q[r-1].v),0))
					return 0;
				r--;
				if(!onright(q[r],a[i].p))
					q[r]=a[i];
			}
			if(l<r)
				p[r]=lineintersect(q[r],q[r-1]);
		}
		while(l<r&&onright(q[l],p[r]))
			r--;
		if(r<=l+1)
			return 0;
		p[l]=lineintersect(q[l],q[r]);
		b.clear();
		for(int i=l;i<=r;i++)
			b.push_back(p[i]);
		return 1;
	}
#undef nxt
	struct circle{
		point o;double r;
		circle(point a={0,0},double b=0.0):o(a),r(b){}
		circle(point a,point b):o(a),r((a-b).len()){}
		circle(point a,point b,point c);
		point gprad(double a){
			return point(o.x+cos(a)*r,o.y+sin(a)*r);
		}
	};
	vector<point>linecircintersect(line l,circle c){
		point t=lineproj(l,c.o);
		double d=(c.o-t).len();
		if(les(c.r,d))return vector<point>();
		if(equ(c.r,d))return vector<point>{t};
		double k=sqrtl(c.r*c.r-d*d);
		return vector<point>{t+unit(l.v)*k,t-unit(l.v)*k};
	}
	vector<point>circintersect(circle a,circle b){
		double d=(a.o-b.o).len();
		if(equ(d,0.0)&&equ(a.r,b.r))
			return vector<point>{{INF,INF}};
		if(les(a.r+b.r,d)||les(d,fabs(a.r-b.r)))
			return vector<point>();
		double ap=(b.o-a.o).ang(),
			at=acos((a.r*a.r+d*d-b.r*b.r)/2.0/d/a.r);
		if(equ(at,0.0))
			return vector<point>{a.gprad(ap)};
		else
			return vector<point>{a.gprad(ap+at),a.gprad(ap-at)};
	}
	vector<line>getcirctang(point p,circle c){
		double d=(p-c.o).len(),a=asin(c.r/d);
		if(les(d,c.r))return vector<line>();
		if(equ(d,c.r))return vector<line>{{p,normal(p-c.o)}};
		return vector<line>{{p,rotate(c.o-p,a)},{p,rotate(c.o-p,-a)}};
	}
	vector<line>getcirctang(circle a,circle b){
		if(les(a.r,b.r))swap(a,b);
		double d=(a.o-b.o).len(),ap=atan2(b.o.y-a.o.y,b.o.x-a.o.x);
		if(equ(d,0.0)&&equ(a.r,b.r))
			return vector<line>{makeseg({INF,INF},{INF,INF})};
		if(les(d,a.r-b.r))
			return vector<line>();
		if(equ(d,a.r-b.r))
			return vector<line>{line(a.gprad(ap),normal(b.o-a.o))};
		double at=acos((a.r-b.r)/d);
		vector<line>res;
		res.push_back(makeseg(a.gprad(ap+at),b.gprad(ap+at)));
		res.push_back(makeseg(a.gprad(ap-at),b.gprad(ap-at)));
		if(equ(d,a.r+b.r))
			res.push_back(makeseg(a.gprad(ap),b.gprad(ap+PI)));
		if(les(a.r+b.r,d)){
			double t=acos((a.r+b.r)/d);
			res.push_back(makeseg(a.gprad(ap+t),b.gprad(ap+t+PI)));
			res.push_back(makeseg(a.gprad(ap-t),b.gprad(ap-t+PI)));
		}
		return res;
	}
	point incenter(point a,point b,point c){
		if(les(cross(b-a,c-a),0.0))swap(b,c);
		return lineintersect(line(b,rotate(c-b,ang(a-b,c-b)/2.0)),
			line(c,rotate(b-c,-ang(a-c,b-c)/2.0)));
	}
	point circumcenter(point a,point b,point c){
		return lineintersect(midline(makeseg(a,b)),
			midline(makeseg(b,c)));
	}
	point centroid(point a,point b,point c){
		return lineintersect(makeseg(a,(b+c)/2),makeseg(b,(a+c)/2));
	}
	point orthocenter(point a,point b,point c){
		return lineintersect(makeseg(a,lineproj(makeseg(b,c),a)),
			makeseg(b,lineproj(makeseg(a,c),b)));
	}
	circle::circle(point a,point b,point c){
		o=circumcenter(a,b,c),r=(o-a).len();
	}
}
using namespace twodgeo;
namespace tridgeo{
	struct point3{
		double x,y,z;
		point3(double a=0.0,double b=0.0,double c=0.0):x(a),y(b),z(){}
		point3 operator+(const point3&rhs)const{
			return point3(x+rhs.x,y+rhs.y,z+rhs.z);
		}
		point3 operator-(const point3&rhs)const{
			return point3(x-rhs.x,y-rhs.y,z-rhs.z);
		}
		point3 operator*(const double&rhs)const{
			return point3(x*rhs,y*rhs,z*rhs);
		}
		point3 operator/(const double&rhs)const{
			return point3(x/rhs,y/rhs,z/rhs);
		}
		int operator<(const point3&rhs)const{
			if(!equ(x,rhs.x))return les(x,rhs.x);
			if(!equ(y,rhs.y))return les(y,rhs.y);
			return les(z,rhs.z);
		}
		int operator==(const point3&rhs)const{
			return equ(x,rhs.x)&&equ(y,rhs.y)&&equ(z,rhs.z);
		}
		double len()const{
			return sqrtl(x*x+y*y+z*z);
		}
	};
	typedef point3 vect3;
	double dot(vect3 a,vect3 b){
		return a.x*b.x+a.y*b.y+a.z*b.z;
	}
	vect3 cross(vect3 a,vect3 b){
		return vect3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
	}
	double ang(vect3 a,vect3 b){
		return acos(dot(a,b)/a.len()/b.len());
	}
	vect3 unit(vect3 a){
		return vect3(a.x/a.len(),a.y/a.len(),a.z/a.len());
	}
	struct plane{
		point3 p;vect3 v;
		plane(point3 a=point3(),vect3 b=vect3()):p(a),v(b){}
	};
	struct line3{
		point3 p;vect3 v;
		line3(point3 a={0,0},vect3 b={0,0}):p(a),v(b){}
		line3(point3 a,point3 b,point3 c):p(a),v(cross(b-a,c-a)){}
	};
	typedef line3 segment3;
	line3 makeseg(point3 a,point3 b){
		return line3(a,b-a);
	}
	double distoplane(point3 a,plane p){
		return fabs(dot(a-p.p,p.v))/p.v.len();
	}
	point3 planeproj(point3 a,plane p){
		return a-p.v*dot(a-p.p,p.v);
	}
	int islineplanepara(line3 l,plane p){
		return equ(dot(p.v,l.v),0.0);
	}
	int issegplaneintersect(line3 l,plane p){
		if(islineplanepara(l,p))return 0;
		double k=dot(p.v,p.p-l.p)/dot(p.v,l.v);
		return leq(0.0,k)&&leq(k,1.0);
	}
	point3 lineplaneintersect(line3 l,plane p){
		return l.p+l.v*dot(p.v,p.p-l.p)/dot(p.v,l.v);
	}
	double triarea(point3 a,point3 b,point3 c){
		return cross(b-a,c-a).len()/2.0;
	}
	double tetravolumn(point3 a,point3 b,point3 c,point3 d){
		return dot(d-a,cross(b-a,c-a))/6.0;
	}
	int pointintri(point3 p,point3 a,point3 b,point3 c){
		return equ(triarea(a,b,c),
			triarea(p,a,b)+triarea(p,b,c)+triarea(p,a,c));
	}
	double distoline(line3 a,point3 b){
		return cross(a.v,b-a.p).len()/a.v.len();
	}
	double distoseg(segment3 a,point3 p){
		point3 x=a.p,y=a.p+a.v;
		if(x==y)
			return (p-x).len();
		vect3 v2=p-x,v3=p-y;
		if(les(dot(a.v,v2),0.0))
			return v2.len();
		if(les(0.0,dot(a.v,v3)))
			return v3.len();
		return distoline(a,p);
	}
}
//using namespace tridgeo;
int n,q;
polygon p,tp;
pslg g,tg;
int main(){
	ios::sync_with_stdio(0);
	cin>>n,p.resize(n);
	for(auto&i:p)cin>>i.x>>i.y;
	polytopslg(p,g);
	for(cin>>q;q--;){
		point a,b;cin>>a.x>>a.y>>b.x>>b.y;
		line l=makeseg(a,b);
		tg=g,tg.push_back(l),tp.clear();
		hfplintersect(tg,tp);
		cout<<fixed<<setprecision(12)<<polygonarea(tp)<<"\n";
	}
}
accuracy: 1
time_ms: 40
memory_kb: 18512
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+50;//注意修改大小
const double eps=1e-8;
const double PI=acos(-1.0);
#define sgn2(x) ((x)>eps?1:((x)<-eps?2:0))//x>0:1;x<0:2;x=0:0.
#define zero(x) (((x)>0?(x):-(x))<eps)//x=0返回1,否则返回0
long long read(){long long x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;}
ll qpow(ll x,ll q,ll Mod){ll ans=1;while(q){if(q&1)ans=ans*x%Mod;q>>=1;x=(x*x)%Mod;}return ans%Mod;}


//-----------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------点------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------------------------------------------------//
inline double R_to_D(double rad){ return 180/PI*rad; }//弧度转角度
inline double D_to_R(double D){ return PI/180*D; }//角度转弧度
int sgn(double x){
    if(fabs(x) < eps)return 0;//x==0
    if(x < 0)return -1;//x<0
    return 1;//x>0
}//!三态函数sgn用于判断相等，减少精度误差问题
struct Point{
    double x, y;
    Point(double x = 0, double y = 0):x(x), y(y){}//构造函数
};
typedef Point Vector;//!注意区分点和向量
typedef vector<Point> Polygon;//定义多边形:即多个Point顺序组成的
Vector operator + (Vector A, Vector B){return Vector(A.x + B.x, A.y + B.y);}//向量 + 向量 = 向量，点 + 向量 = 向量
Vector operator - (Point A, Point B){return Vector(A.x - B.x, A.y - B.y);}//点 - 点 = 向量(向量AB = B - A)
Vector operator * (Vector A, double p){return Vector(A.x * p, A.y * p);}//向量 * 数 = 向量
Vector operator / (Vector A, double p){return Vector(A.x / p, A.y / p);}//!向量 / 数= 向量
bool operator < (const Point& A, const Point& B) {return A.x < B.x || (A.x == B.x && A.y < B. y);}//点or向量 的比较函数(优先横向排序)
bool operator == (const Point& A, const Point& B){return !sgn(A.x - B.x) && !sgn(A.y - B.y);}//点or向量 的相等函数
double Polar_angle(Vector A){return atan2(A.y, A.x);}//求极角:在极坐标系中，平面上任何一点到极点的连线和极轴的夹角叫做极角。单位弧度rad
double Dot(Vector A, Vector B){return A.x * B.x + A.y * B.y;}//点积(满足交换律)：a·b=|a||b|cos<a,b> A.x*B.x+A.y*B.y;
double Cross(Vector A, Vector B){return A.x *  B.y - B.x * A.y;}//向量的叉积(不满足交换律)：等于两向量有向面积的二倍(若B在A的逆时针方向，则为正值;顺时针则为负值;共线则为0).cross(x, y) = -cross(y, x)
double LeftTest_Point(Point A, Point B, Point C){return Cross(B - A, C - B);}//判断向量BC是不是向AB的逆时针方向（左边）转(ToLeftTest);也可看作一个点C是否在向量AB的左边:是则>0,不是则<0,共线则=0
double LeftTest_Vector(Vector A, Vector B){return Cross(A,B);}//判断向量B是不是向量A的逆时针方向（左边）:是则>0,不是则<0,共线则=0
double Length(Vector A){return sqrt(Dot(A, A));}//取模
double Angle(Vector A, Vector B){return acos(Dot(A, B) / Length(A) / Length(B));}//计算两向量夹角(Angle),返回值为弧度制下的夹角
double Area2(Point A, Point B, Point C){return Cross(B - A, C - A);}//交点为A的两个向量AB和AC,然后求这两个向量的叉积(叉乘),ABxAC=平行四边形的面积
Vector Normal(Vector A) {double L = Length(A);return Vector(-A.y / L, A.x / L);}//向量A的法向量：向量A逆时针旋转九十度之后的单位向量
Vector Format(Vector A) {double L = Length(A);return Vector(A.x / L,A.y / L);}//向量A的单位向量化
Vector Rotate(Vector A, double rad){return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}//向量A逆时针旋转后的向量:x'=xcosa -ysina, y'= xsina+ycosa,rad:弧度且为逆时针旋转的角
Point Turn_B(Point A, Point B, double rad){
    double x = (A.x-B.x) * cos(rad) + (A.y-B.y) * sin(rad) + B.x;
    double y = - (A.x-B.x) * sin(rad) + (A.y-B.y) * cos(rad) + B.y; 
    return Point(x,y);
}//将点A绕点B顺时针旋转rad(弧度)


//-----------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------直线----------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------------------------------------------------//
struct Line{
    Vector v;//方向向量。左边就是对应的半平面
    Point p;//直线上任意一点
    Line(Vector v, Point p):v(v), p(p) {}
    //如果需要使用极角就使用下面的代码，主要注释上面一行
    // double deg;//极角
    // Line(Vector v,Point p):p(p), v(v){deg = atan2(v.y, v.x);}
    // bool operator < (const Line& L)const {//排序时使用的比较运算符 由x正向逆时针到x正向
    //     return deg < L.deg;
    // }
};//直线定义:P'=P+v*t
int Relation(Point A, Point B, Point C){int c = sgn(Cross((B - A), (C - A)));if(c < 0) return 1;else if(c > 0) return -1;return 0;}//点C和直线AB关系:1在左侧;-1在右侧;0在直线上.
Point Get_line_intersection(Point P,Vector V,Point Q,Vector W){
    Vector U = P - Q;double t = Cross(W, U) / Cross(V, W);return P + V * t;
}//两直线交点:(直线AB:A+tv(v为向量AB,t为参数,A为起点)).调用前要确保两直线p + tv和Q + tw之间有唯一交点,当且仅当Corss(v, w) != 0;（t是参数）
double Distance_point_to_line(Point P, Point A, Point B){Vector v1 = B - A, v2 = P - A;return fabs(Cross(v1, v2) / Length(v1));}//如果不取绝对值，那么得到的是有向距离}//点P到直线AB的距离
double Distance_point_to_segment(Point P, Point A, Point B)
{
    if(A == B) return Length(P - A);//（如果重合那么就是两个点之间的距离，直接转成向量求距离即可）
    Vector v1 = B - A, v2 = P - A, v3 = P - B;
    if(sgn(Dot(v1, v2)) < 0) return Length(v2);//A点左边
    if(sgn(Dot(v1, v3)) > 0)return Length(v3);//B点右边
    return fabs(Cross(v1, v2) / Length(v1));//垂线的距离
}//点P到线段AB的距离:垂线距离或者PA或者PB距离
bool OnSegment(Point P, Point A, Point B){return sgn(Cross(A-P, B-P)) == 0 && sgn(Dot(A-P, B-P)) <= 0;}//判断点p是否在线段AB上(包含端点AB，如果不包含AB则<=改为<)
bool Segment_proper_intersection(Point a1, Point a2, Point b1, Point b2){
    double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1);double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);
    //if判断控制是否允许线段在端点处相交，根据需要添加
    if(!sgn(c1) || !sgn(c2) || !sgn(c3) || !sgn(c4)){
        bool f1 = OnSegment(b1, a1, a2), f2 = OnSegment(b2, a1, a2), f3 = OnSegment(a1, b1, b2), f4 = OnSegment(a2, b1, b2);
        bool f = (f1|f2|f3|f4);
        return f;
    }
    return (sgn(c1)*sgn(c2) < 0 && sgn(c3)*sgn(c4) < 0);
}//判断线段a1a2与b1b2是否相交（if控制端点相交）
Point Get_line_projection(Point P, Point A, Point B){Vector v = B - A;return A + v * (Dot(v, P - A) / Dot(v, v));}//求点P在直线AB上的投影点
Point FootPoint(Point P, Point A, Point B){
    Vector x = P - A, y = P - B, z = B - A;
    double len1 = Dot(x, z) / Length(z), len2 = - 1.0 * Dot(y, z) / Length(z);//分别计算AP,BP在AB,BA上的投影
    return A + z * (len1 / (len1 + len2));//点A加上向量AF
}//求点P到直线AB的垂足
Point Symmetry_PL(Point P, Point A, Point B){return P + (FootPoint(P, A, B) - P) * 2; }//求点P到直线AB的对称点


//-----------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------多边形----------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------------------------------------------------//
//外心：三边中垂线交点，到三角形三个顶点距离相同（外接圆圆心）
//内心：角平分线的交点，到三角形三边的距离相同（内切圆圆心）
//垂心：三条垂线的交点
//重心：三条中线的交点，到三角形三顶点距离的平方和最小的点，三角形内到三边距离之积最大的点(x=(x1+x2+x3),y=(y1+y2+y3))
double Convex_polygon_area(Point* p, int n){//逆时针储存所有顶点,下标从0开始
    double area = 0;for(int i = 1; i <= n - 2; ++ i)area += Cross(p[i] - p[0], p[i + 1] - p[0]);return area / 2;//return fabs(area / 2);//不加的话求的是有向面积，逆时针为正，顺时针为负
}//求凸多边形的有向面积
double Polygon_area(Point* p, int n){//逆时针储存所有顶点,下标从0开始
    double area = 0;for(int i = 1; i <= n - 2; ++ i)area += Cross(p[i] - p[0], p[i + 1] - p[0]);return area / 2;
}//求非凸多边形的有向面积
int is_point_in_polygon(Point p, Point* poly,int n){//待判断的点和该多边形的所有点的合集
    int wn = 0;
    for(int i = 0; i < n; ++i){
        if(OnSegment(p, poly[i], poly[(i+1)%n])) return -1;
        int k = sgn(Cross(poly[(i+1)%n] - poly[i], p - poly[i])),d1 = sgn(poly[i].y - p.y),d2 = sgn(poly[(i+1)%n].y - p.y);
        if(k > 0 && d1 <= 0 && d2 > 0) wn++;
        if(k < 0 && d2 <= 0 && d1 > 0) wn--;
    }
    if(wn != 0)return 1;
    return 0;
}//判断点P是否在多边形内，若点在多边形内返回1，在多边形外部返回0，在多边形上返回-1
//判断点P是否在凸多边形内,只需要判断点P是否在所有边的左边（按逆时针顺序排列的顶点集）可以使用LeftTest_Point
int is_convex(Point* p,int n){int s[3]={1,1,1};for(int i=0;i<n&&s[1]|s[2];i++)s[sgn2(Cross(p[(i+1)%n]-p[i],p[(i+2)%n]-p[i]))]=0;return s[1]|s[2];}//判定凸多边形,允许相邻边共线.顶点按顺时针或逆时针给出
int is_convex_v2(Point* p,int n){int s[3]={1,1,1};for (int i=0;i<n&&s[0]&&s[1]|s[2];i++)s[sgn2(Cross(p[(i+1)%n]-p[i],p[(i+2)%n]-p[i]))]=0;return s[0]&&s[1]|s[2];}//判定凸多边形,不允许相邻边共线.顺时针或逆时针给出
int inside_convex(Point q,Point* p,int n){int s[3]={1,1,1};for (int i=0;i<n&&s[1]|s[2];i++)s[sgn2(Cross(p[(i+1)%n]-p[i],q-p[i]))]=0;return s[1]|s[2];}//判点q在凸多边形内或边上,顶点按顺时针或逆时针给出
int inside_convex_v2(Point q,Point* p,int n){int s[3]={1,1,1};for (int i=0;i<n&&s[0]&&s[1]|s[2];i++)s[sgn2(Cross(p[(i+1)%n]-p[i],q-p[i]))]=0;return s[0]&&s[1]|s[2];}//判点q在凸多边形内,顶点按顺时针或逆时针给出,在多边形边上返回0
int inside_polygon(Point q,Point* p,int n,int on_edge=1){//on_edge表示点在多边形边上时的返回值,默认为1
	Point q2;int i=0,count=0;
    const int offset=10000;//offset为多边形坐标上限,根据题意修改
	while (i<n){
        for (count=i=0,q2.x=rand()+offset,q2.y=rand()+offset;i<n;i++){
            if (zero(Cross(q-p[(i+1)%n],p[i]-p[(i+1)%n]))&&(p[i].x-q.x)*(p[(i+1)%n].x-q.x)<eps&&(p[i].y-q.y)*(p[(i+1)%n].y-q.y)<eps)return on_edge;
			else if (zero(Cross(q-p[i],q2-p[i])))break;
			else if (Cross(q-q2,p[i]-q2)*Cross(q-q2,p[(i+1)%n]-q2)<-eps&&Cross(p[i]-p[(i+1)%n],q-p[(i+1)%n])*Cross(p[i]-p[(i+1)%n],q2-p[(i+1)%n])<-eps)count++;
        }
    }
    if(count&1)return 2;return 0;
}//判点在任意多边形内,顶点按顺时针或逆时针给出.点q在多边形内则为2,在边上则为1(可以修改on_edge),在外则为0

int opposite_side(Point p1,Point p2,Point l1,Point l2){return Cross(l1-l2,p1-l2)*Cross(l1-l2,p2-l2)<-eps;}
int dot_online_in(Point p,Point l1,Point l2){return zero(Cross(p-l2,l1-l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps;}
int inside_polygon(Point l1,Point l2,Point* p,int n){
    const int MAXN=1000;//注意根据n的范围进行修改
	Point t[MAXN],tt;int i,j,k=0;
	if (!inside_polygon(l1,p,n)||!inside_polygon(l2,p,n))return 0;
	for (i=0;i<n;i++){
        if (opposite_side(l1,l2,p[i],p[(i+1)%n])&&opposite_side(p[i],p[(i+1)%n],l1,l2))return 0;
		else if (dot_online_in(l1,p[i],p[(i+1)%n]))t[k++]=l1;
		else if (dot_online_in(l2,p[i],p[(i+1)%n]))t[k++]=l2;
		else if (dot_online_in(p[i],l1,l2))t[k++]=p[i];
    }
	for (i=0;i<k;i++){
        for (j=i+1;j<k;j++){
			tt.x=(t[i].x+t[j].x)/2;tt.y=(t[i].y+t[j].y)/2;
			if(!inside_polygon(tt,p,n))return 0;			
		}
    }	
	return 1;
}//判线段l1l2在任意多边形内,顶点按顺时针或逆时针给出,与边界相交或在内部返回1，否则返回0
Point Polygon_center(Point *p, int n) {
    Point ans(0, 0);
    if(Polygon_area(p, n) == 0)return ans;
    for (int i = 0; i < n; i++)ans = ans + (p[i] + p[(i + 1) % n]) * Cross(p[i], p[(i + 1) % n]); //面积有正负
    return ans / Polygon_area(p, n) / 6.;
}//多边形重心,将多边形三角剖分，算出每个三角形重心（三角形重心是3点坐标平均值）对每个三角形有向面积求加权平均值
bool cmp_ConvexHull(Point A,Point B){return A.y < B.y || (A.y == B.y && A.x < B. x);}//竖向排序，默认从下左角开始逆时针输出
int ConvexHull(Point* p, int n, Point* ch){//下标都是从0开始，ch按照逆时针存储的
    sort(p, p + n);int m = 0;
    for(int i = 0; i < n;i++){//下凸包
        //如果叉积<=0说明新边斜率小说明已经不是凸包边了，赶紧踢走
        while(m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)m -- ;
        ch[m ++ ] = p[i];//<=:一条边有两给端点;<:边上可以有多个输入点 注意根据题意进行修改(求凸包直径的时候是<=)
    }
    int k = m;
    for(int i = n - 2; i >= 0;i--){//上凸包
        while(m > k && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)m -- ;
        ch[m ++ ] = p[i];//<=:一条边有两给端点;<:边上可以有多个输入点 注意根据题意进行修改(求凸包直径的时候是<=)
    }
    if(n > 1) m -- ;return m;//返回凸包顶点个数
}//计算凸包,输入点数组p.输出点数组ch.输入不能有重复的点，函数执行完后的输入点的顺序将被破坏(因为要排序，可以加一个数组存原来的id)
double Rotating_calipers(Point* con,int n){//传入最小凸包的点数组
    int op = 1;double ans = 0;
    for(int i = 0; i < n; ++ i){
        while(Cross((con[i] - con[op]), (con[i + 1] - con[i])) < Cross((con[i] - con[op + 1]), (con[i + 1] - con[i])))op = (op + 1) % n;//（写成<=会被两个点的数据卡掉，所以必须写成<）
            ans = max(ans, max(Dot(con[i] - con[op],con[i] - con[op]), Dot(con[i + 1] - con[op],con[i + 1] - con[op])));
    }
    return ans;
}//旋转卡壳,返回凸包的直径的平方
Polygon CutPolygon(Polygon poly,const Point& a,const Point& b) {//poly中的点从0开始
    Polygon newpoly;int n=poly.size();
    for(int i=0; i<n; i++){
        Point c=poly[i],d=poly[(i+1)%n];
        if(sgn(Cross(b-a,c-a))>=0)newpoly.push_back(c);
        if(sgn(Cross(b-a,c-d))!=0){
            Point ip=Get_line_intersection(a,b-a,c,d-c);
            if(OnSegment(ip,c,d))newpoly.push_back(ip);
        }
    }
    return newpoly;
}//有向直线ab切割多边形,返回左侧
Point a[maxn],p,ans[maxn],b[maxn];int n,T;
int main(){
    // freopen("10.in","r",stdin);
    // freopen("10.out","w",stdout);
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i].x>>a[i].y;
    cin>>T;
    while(T--){
        Point a1,a2;
        cin>>a1.x>>a1.y>>a2.x>>a2.y;
        Polygon s;
        for(int i=0;i<n;i++)s.push_back(a[i]);
        Polygon s2;
        s2=CutPolygon(s,a1,a2);
        for(int i=0;i<s2.size();i++)b[i]=s2[i];
        double ans=abs(Convex_polygon_area(b,s2.size()));
        printf("%.8lf\n",ans);
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50108
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1e6 + 10;

const double eps = 1e-9;
const double PI = acos(-1.0);
const double dinf = 1e99;
const ll inf = 0x3f3f3f3f3f3f3f3f;
struct Line;

struct Point {
    double x, y;

    Point() { x = y = 0; }

    Point(const Line &a);

    Point(const double &a, const double &b) : x(a), y(b) {}

    Point operator+(const Point &a) const {
        return {x + a.x, y + a.y};
    }

    Point operator-(const Point &a) const {
        return {x - a.x, y - a.y};
    }

    Point operator*(const double &a) const {
        return {x * a, y * a};
    }

    Point operator/(const double &d) const {
        return {x / d, y / d};
    }

    bool operator==(const Point &a) const {
        return abs(x - a.x) + abs(y - a.y) < eps;
    }

    void standardize() {
        *this = *this / sqrt(x * x + y * y);
    }
};

double norm(const Point &p) { return p.x * p.x + p.y * p.y; }

Point orth(const Point &a) { return Point(-a.y, a.x); }

double dist(const Point &a, const Point &b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

double dist2(const Point &a, const Point &b) {
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

struct Line {
    Point s, t;

    Line() {}

    Line(const Point &a, const Point &b) : s(a), t(b) {}

};


struct Circle {
    Point o;
    double r;

    Circle() {}

    Circle(Point P, double R = 0) { o = P, r = R; }
};

double length(const Point &p) {
    return sqrt(p.x * p.x + p.y * p.y);
}

double length(const Line &l) {
    Point p(l);
    return length(p);
}

Point::Point(const Line &a) { *this = a.t - a.s; }

istream &operator>>(istream &in, Point &a) {
    in >> a.x >> a.y;
    return in;
}

ostream &operator<<(ostream &out, Point &a) {
    out << fixed << setprecision(10) << a.x << ' ' << a.y;
    return out;
}

double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }

double det(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }

int sgn(const double &x) { return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1); }

double sqr(const double &x) { return x * x; }

Point rotate(const Point &a, const double &ang) {
    double x = cos(ang) * a.x - sin(ang) * a.y;
    double y = sin(ang) * a.x + cos(ang) * a.y;
    return {x, y};
}

//点在线段上 <=0 包含端点
bool sp_on(const Line &seg, const Point &p) {
    Point a = seg.s, b = seg.t;
    return !sgn(det(p - a, b - a)) && sgn(dot(p - a, p - b)) <= 0;
}

bool lp_on(const Line &line, const Point &p) {
    Point a = line.s, b = line.t;
    return !sgn(det(p - a, b - a));
}

//等于不包含共线
int andrew(Point *point, Point *convex, int n) {
    sort(point, point + n, [](Point a, Point b) {
        if (a.x != b.x) return a.x < b.x;
        return a.y < b.y;
    });
    int top = 0;
    for (int i = 0; i < n; i++) {
        while ((top > 1) && det(convex[top - 1] - convex[top - 2], point[i] - convex[top - 1]) <= 0)
            top--;
        convex[top++] = point[i];
    }
    int tmp = top;
    for (int i = n - 2; i >= 0; i--) {
        while ((top > tmp) && det(convex[top - 1] - convex[top - 2], point[i] - convex[top - 1]) <= 0)
            top--;
        convex[top++] = point[i];
    }
    if (n > 1) top--;
    return top;
}

double slope(const Point &a, const Point &b) { return (a.y - b.y) / (a.x - b.x); }

double slope(const Line &a) { return slope(a.s, a.t); }

Point ll_intersection(const Line &a, const Line &b) {
    double s1 = det(Point(a), b.s - a.s), s2 = det(Point(a), b.t - a.s);
    if (sgn(s1) == 0 && sgn(s2) == 0) return a.s;
    return (b.s * s2 - b.t * s1) / (s2 - s1);
}

int ss_cross(const Line &a, const Line &b, Point &p) {
    int d1 = sgn(det(a.t - a.s, b.s - a.s));
    int d2 = sgn(det(a.t - a.s, b.t - a.s));
    int d3 = sgn(det(b.t - b.s, a.s - b.s));
    int d4 = sgn(det(b.t - b.s, a.t - b.s));
    if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2) {
        p = ll_intersection(a, b);
        return 1;
    }
    if (!d1 && sp_on(a, b.s)) {
        p = b.s;
        return 2;
    }
    if (!d2 && sp_on(a, b.t)) {
        p = b.t;
        return 2;
    }
    if (!d3 && sp_on(b, a.s)) {
        p = a.s;
        return 2;
    }
    if (!d4 && sp_on(b, a.t)) {
        p = a.t;
        return 2;
    }
    return 0;
}


int ccw(const Point &a, Point b, Point c) {
    b = b - a, c = c - a;
    if (sgn(det(b, c)) > 0) return +1;  // "COUNTER_CLOCKWISE"
    if (sgn(det(b, c)) < 0) return -1; // "CLOCKWISE"
    if (sgn(dot(b, c)) < 0) return +2;      // "ONLINE_BACK"
    if (sgn(norm(b) - norm(c)) < 0) return -2;  // "ONLINE_FRONT"
    return 0;                         // "ON_SEGMENT"
}


Point project(const Line &l, const Point &p) {
    Point base(l);
    double r = dot(base, p - l.s) / sqr(length(base));
    return l.s + (base * r);
}

double sp_dist(const Line &l, const Point &p) {
    if (l.s == l.t) return dist(l.s, p);
    Point x = p - l.s, y = p - l.t, z = l.t - l.s;
    if (sgn(dot(x, z)) < 0)return length(x);//P距离A更近
    if (sgn(dot(y, z)) > 0)return length(y);//P距离B更近
    return abs(det(x, z) / length(z));//面积除以底边长
}

double lp_dist(const Line &l, const Point &p) {
    Point x = p - l.s, y = p - l.t, z = l.t - l.s;
    return abs(det(x, z) / length(z));//面积除以底边长
}

int cl_cross(const Circle &c, const Line &l, pair<Point, Point> &ans) {
    Point a = c.o;
    double r = c.r;
    Point pr = project(l, a);
    double dis = dist(pr, a);
    double tmp = r * r - dis * dis;
    if (sgn(tmp) == 1) {
        double base = sqrt(max(0.0, r * r - dis * dis));
        Point e(l);
        e.standardize();
        e = e * base;
        ans = make_pair(pr + e, pr - e);
        return 2;
    } else if (sgn(tmp) == 0) {
        ans = make_pair(pr, pr);
        return 1;
    } else return 0;
}

int intersectCS(Circle c, Line l) {//交点个数，下面cs_cross用到
    if (sgn(norm(project(l, c.o) - c.o) - c.r * c.r) > 0) return 0;
    double d1 = length(c.o - l.s), d2 = length(c.o - l.t);
    if (sgn(d1 - c.r) <= 0 && sgn(d2 - c.r) <= 0) return 0;
    if ((sgn(d1 - c.r) < 0 && sgn(d2 - c.r) > 0) || (sgn(d1 - c.r) > 0 && sgn(d2 - c.r) < 0)) return 1;
    Point h = project(l, c.o);
    if (dot(l.s - h, l.t - h) < 0) return 2;
    return 0;
}

int cs_cross(Circle c, Line s, pair<Point, Point> &ans) {//圆和线段交点
    Line l(s);
    int num = cl_cross(c, l, ans);
    int res = intersectCS(c, s);
    if (res == 2) return 2;
    if (num > 1) {
        if (dot(l.s - ans.first, l.t - ans.first) > 0) swap(ans.first, ans.second);
        ans.second = ans.first;
    }
    return res;
}


int cc_cross(const Circle &cir1, const Circle &cir2, pair<Point, Point> &ans) {
    const Point &c1 = cir1.o, &c2 = cir2.o;
    const double &r1 = cir1.r, &r2 = cir2.r;
    double x1 = c1.x, x2 = c2.x, y1 = c1.y, y2 = c2.y;
    double d = length(c1 - c2);
    if (sgn(fabs(r1 - r2) - d) > 0) return 0;  //内含
    if (sgn(r1 + r2 - d) < 0) return 4; //相离
    double a = r1 * (x1 - x2) * 2, b = r1 * (y1 - y2) * 2, c = r2 * r2 - r1 * r1 - d * d;
    double p = a * a + b * b, q = -a * c * 2, r = c * c - b * b;

    double cosa, sina, cosb, sinb;
    //One Intersection
    if (sgn(d - (r1 + r2)) == 0 || sgn(d - fabs(r1 - r2)) == 0) {
        cosa = -q / p / 2;
        sina = sqrt(1 - sqr(cosa));
        Point p0(x1 + r1 * cosa, y1 + r1 * sina);
        if (sgn(dist(p0, c2) - r2)) p0.y = y1 - r1 * sina;
        ans = pair<Point, Point>(p0, p0);
        if (sgn(r1 + r2 - d) == 0) return 3;    //外切
        else return 1;  //内切
    }
    //Two Intersections
    double delta = sqrt(q * q - p * r * 4);
    cosa = (delta - q) / p / 2;
    cosb = (-delta - q) / p / 2;
    sina = sqrt(1 - sqr(cosa));
    sinb = sqrt(1 - sqr(cosb));
    Point p1(x1 + r1 * cosa, y1 + r1 * sina);
    Point p2(x1 + r1 * cosb, y1 + r1 * sinb);
    if (sgn(dist(p1, c2) - r2)) p1.y = y1 - r1 * sina;
    if (sgn(dist(p2, c2) - r2)) p2.y = y1 - r1 * sinb;
    if (p1 == p2) p1.y = y1 - r1 * sina;
    ans = pair<Point, Point>(p1, p2);
    return 2;   //  相交
}

Point lp_sym(const Line &l, const Point &p) {
    return p + (project(l, p) - p) * 2;
}

double alpha(const Point &t1, const Point &t2) {
    double theta;
    theta = atan2((double) t2.y, (double) t2.x) - atan2((double) t1.y, (double) t1.x);
    if (sgn(theta) < 0)
        theta += 2.0 * PI;
    return theta;
}

int pip(const Point *P, const int &n, const Point &a) {//【射线法】判断点A是否在任意多边形Poly以内
    int cnt = 0;
    double tmp;
    for (int i = 1; i <= n; ++i) {
        int j = i < n ? i + 1 : 1;
        if (sp_on(Line(P[i], P[j]), a))return 2;//点在多边形上
        if (a.y >= min(P[i].y, P[j].y) && a.y < max(P[i].y, P[j].y))//纵坐标在该线段两端点之间
            tmp = P[i].x + (a.y - P[i].y) / (P[j].y - P[i].y) * (P[j].x - P[i].x), cnt += sgn(tmp - a.x) > 0;//交点在A右方
    }
    return cnt & 1;//穿过奇数次则在多边形以内
}

bool pip_convex_jud(const Point &a, const Point &L, const Point &R) {//判断AL是否在AR右边
    return sgn(det(L - a, R - a)) > 0;//必须严格以内
}

bool pip_convex(const Point *P, const int &n, const Point &a) {//【二分法】判断点A是否在凸多边形Poly以内
    //点按逆时针给出
    if (pip_convex_jud(P[0], a, P[1]) || pip_convex_jud(P[0], P[n - 1], a)) return 0;//在P[0_1]或P[0_n-1]外
    if (sp_on(Line(P[0], P[1]), a) || sp_on(Line(P[0], P[n - 1]), a)) return 2;//在P[0_1]或P[0_n-1]上
    int l = 1, r = n - 2;
    while (l < r) {//二分找到一个位置pos使得P[0]_A在P[0_pos],P[0_(pos+1)]之间
        int mid = (l + r + 1) >> 1;
        if (pip_convex_jud(P[0], P[mid], a))l = mid;
        else r = mid - 1;
    }
    if (pip_convex_jud(P[l], a, P[l + 1]))return 0;//在P[pos_(pos+1)]外
    if (sp_on(Line(P[l], P[l + 1]), a))return 2;//在P[pos_(pos+1)]上
    return 1;
}
// 多边形是否包含线段
// 因此我们可以先求出所有和线段相交的多边形的顶点，然后按照X-Y坐标排序(X坐标小的排在前面，对于X坐标相同的点，Y坐标小的排在前面，
// 这种排序准则也是为了保证水平和垂直情况的判断正确)，这样相邻的两个点就是在线段上相邻的两交点，如果任意相邻两点的中点也在多边形内，
// 则该线段一定在多边形内。

int pp_judge(Point *A, int n, Point *B, int m) {//【判断多边形A与多边形B是否相离】
    for (int i1 = 1; i1 <= n; ++i1) {
        int j1 = i1 < n ? i1 + 1 : 1;
        for (int i2 = 1; i2 <= m; ++i2) {
            int j2 = i2 < m ? i2 + 1 : 1;
            Point tmp;
            if (ss_cross(Line(A[i1], A[j1]), Line(B[i2], B[j2]), tmp)) return 0;//两线段相交
            if (pip(B, m, A[i1]) || pip(A, n, B[i2]))return 0;//点包含在内
        }
    }
    return 1;
}

double area(Point *P, int n) {//【任意多边形P的面积】
    double S = 0;
    for (int i = 0; i < n; i++) S += det(P[i], P[(i + 1) % n]);
    return S * 0.5;
}

double pc_area(Point *p, int n, const Circle &c) {
    if (n < 3) return 0;
    function<double(Circle, Point, Point)> dfs = [&](Circle c, Point a, Point b) {
        Point va = c.o - a, vb = c.o - b;
        double f = det(va, vb), res = 0;
        if (sgn(f) == 0) return res;
        if (sgn(max(length(va), length(vb)) - c.r) <= 0) return f;
        Point d(dot(va, vb), det(va, vb));
        if (sgn(sp_dist(Line(a, b), c.o) - c.r) >= 0) return c.r * c.r * atan2(d.y, d.x);
        pair<Point, Point> u;
        int cnt = cs_cross(c, Line(a, b), u);
        if (cnt == 0) return res;
        if (cnt > 1 && sgn(dot(u.second - u.first, a - u.first)) > 0) swap(u.first, u.second);
        res += dfs(c, a, u.first);
        if (cnt == 2) res += dfs(c, u.first, u.second) + dfs(c, u.second, b);
        else if (cnt == 1) res += dfs(c, u.first, b);
        return res;
    };
    double res = 0;
    for (int i = 0; i < n; i++) {
        res += dfs(c, p[i], p[(i + 1) % n]);
    }
    return res * 0.5;
}

Line Q[N];

int judge(Line L, Point a) { return sgn(det(a - L.s, L.t - L.s)) > 0; }//判断点a是否在直线L的右边
int halfcut(Line *L, int n, Point *P) {//【半平面交】
    sort(L, L + n, [](const Line &a, const Line &b) {
        double d = atan2((a.t - a.s).y, (a.t - a.s).x) - atan2((b.t - b.s).y, (b.t - b.s).x);
        return sgn(d) ? sgn(d) < 0 : judge(a, b.s);
    });

    int m = n;
    n = 0;
    for (int i = 0; i < m; ++i)
        if (i == 0 || sgn(atan2(Point(L[i]).y, Point(L[i]).x) - atan2(Point(L[i - 1]).y, Point(L[i - 1]).x)))
            L[n++] = L[i];
    int h = 1, t = 0;
    for (int i = 0; i < n; ++i) {
        while (h < t && judge(L[i], ll_intersection(Q[t], Q[t - 1]))) --t;//当队尾两个直线交点不是在直线L[i]上或者左边时就出队
        while (h < t && judge(L[i], ll_intersection(Q[h], Q[h + 1]))) ++h;//当队头两个直线交点不是在直线L[i]上或者左边时就出队
        Q[++t] = L[i];

    }
    while (h < t && judge(Q[h], ll_intersection(Q[t], Q[t - 1]))) --t;
    while (h < t && judge(Q[t], ll_intersection(Q[h], Q[h + 1]))) ++h;
    n = 0;
    for (int i = h; i <= t; ++i) {
        P[n++] = ll_intersection(Q[i], Q[i < t ? i + 1 : h]);
    }
    return n;
}

Point V1[N], V2[N];

int mincowski(Point *P1, int n, Point *P2, int m, Point *V) {//【闵可夫斯基和】求两个凸包{P1},{P2}的向量集合{V}={P1+P2}构成的凸包
    for (int i = 0; i < n; ++i) V1[i] = P1[(i + 1) % n] - P1[i];
    for (int i = 0; i < m; ++i) V2[i] = P2[(i + 1) % m] - P2[i];
    int t = 0, i = 0, j = 0;
    V[t++] = P1[0] + P2[0];
    while (i < n && j < m) V[t] = V[t - 1] + (sgn(det(V1[i], V2[j])) > 0 ? V1[i++] : V2[j++]), t++;
    while (i < n) V[t] = V[t - 1] + V1[i++], t++;
    while (j < m) V[t] = V[t - 1] + V2[j++], t++;
    return t;
}

Circle external_circle(const Point &A, const Point &B, const Point &C) {//【三点确定一圆】向量垂心法
    Point P1 = (A + B) * 0.5, P2 = (A + C) * 0.5;
    Line R1 = Line(P1, P1 + orth(B - A));
    Line R2 = Line(P2, P2 + orth(C - A));
    Circle O;
    O.o = ll_intersection(R1, R2);
    O.r = length(A - O.o);
    return O;
}

Circle internal_circle(const Point &A, const Point &B, const Point &C) {
    double a = dist(B, C), b = dist(A, C), c = dist(A, B);
    double s = (a + b + c) / 2;
    double S = sqrt(max(0.0, s * (s - a) * (s - b) * (s - c)));
    double r = S / s;

    return Circle((A * a + B * b + C * c) / (a + b + c), r);
}


struct ConvexHull {

    int op;

    struct cmp {
        bool operator()(const Point &a, const Point &b) const {
            return sgn(a.x - b.x) < 0 || sgn(a.x - b.x) == 0 && sgn(a.y - b.y) < 0;
        }
    };

    set<Point, cmp> s;

    ConvexHull(int o) {
        op = o;
        s.clear();
    }

    inline int PIP(Point P) {
        set<Point>::iterator it = s.lower_bound(Point(P.x, -dinf));//找到第一个横坐标大于P的点
        if (it == s.end())return 0;
        if (sgn(it->x - P.x) == 0) return sgn((P.y - it->y) * op) <= 0;//比较纵坐标大小
        if (it == s.begin())return 0;
        set<Point>::iterator j = it, k = it;
        --j;
        return sgn(det(P - *j, *k - *j) * op) >= 0;//看叉姬1
    }

    inline int judge(set<Point>::iterator it) {
        set<Point>::iterator j = it, k = it;
        if (j == s.begin())return 0;
        --j;
        if (++k == s.end())return 0;
        return sgn(det(*it - *j, *k - *j) * op) >= 0;//看叉姬
    }

    inline void insert(Point P) {
        if (PIP(P))return;//如果点P已经在凸壳上或凸包里就不插入了
        set<Point>::iterator tmp = s.lower_bound(Point(P.x, -dinf));
        if (tmp != s.end() && sgn(tmp->x - P.x) == 0)s.erase(tmp);//特判横坐标相等的点要去掉
        s.insert(P);
        set<Point>::iterator it = s.find(P), p = it;
        if (p != s.begin()) {
            --p;
            while (judge(p)) {
                set<Point>::iterator temp = p--;
                s.erase(temp);
            }
        }
        if ((p = ++it) != s.end()) {
            while (judge(p)) {
                set<Point>::iterator temp = p++;
                s.erase(temp);
            }
        }
    }
} up(1), down(-1);

int PIC(Circle C, Point a) { return sgn(length(a - C.o) - C.r) <= 0; }//判断点A是否在圆C内
void Random(Point *P, int n) { for (int i = 0; i < n; ++i)swap(P[i], P[(rand() + 1) % n]); }//随机一个排列
Circle min_circle(Point *P, int n) {//【求点集P的最小覆盖圆】 O(n)
//  random_shuffle(P,P+n);
    Random(P, n);
    Circle C = Circle(P[0], 0);
    for (int i = 1; i < n; ++i)
        if (!PIC(C, P[i])) {
            C = Circle(P[i], 0);
            for (int j = 0; j < i; ++j)
                if (!PIC(C, P[j])) {
                    C.o = (P[i] + P[j]) * 0.5, C.r = length(P[j] - C.o);
                    for (int k = 0; k < j; ++k) if (!PIC(C, P[k])) C = external_circle(P[i], P[j], P[k]);
                }
        }
    return C;
}


int temp[N];

double closest_point(Point *p, int n) {
    function<double(int, int)> merge = [&](int l, int r) {
        double d = dinf;
        if (l == r) return d;
        if (l + 1 == r) return dist(p[l], p[r]);
        int mid = (l + r) >> 1;
        double d1 = merge(l, mid);
        double d2 = merge(mid + 1, r);
        d = min(d1, d2);
        int i, j, k = 0;
        for (i = l; i <= r; i++) {
            if (sgn(abs(p[mid].x - p[i].x) - d) <= 0)
                temp[k++] = i;

        }
        sort(temp, temp + k, [&](const int &a, const int &b) {
            return sgn(p[a].y - p[b].y) < 0;
        });
        for (i = 0; i < k; i++) {
            for (j = i + 1; j < k && sgn(p[temp[j]].y - p[temp[i]].y - d) <= 0; j++) {
                double d3 = dist(p[temp[i]], p[temp[j]]);
                d = min(d, d3);
            }
        }
        return d;
    };
    sort(p, p + n, [&](const Point &a, const Point &b) {
        if (sgn(a.x - b.x) == 0) return sgn(a.y - b.y) < 0;
        else return sgn(a.x - b.x) < 0;
    });
    return merge(0, n - 1);
}

int tangent(const Circle &c1, const Point &p2, pair<Point, Point> &ans) { //圆和点切线
    Point tmp = c1.o - p2;
    int sta;
    if (sgn(norm(tmp) - c1.r * c1.r) < 0) return 0;
    else if (sgn(norm(tmp) - c1.r * c1.r) == 0) sta = 1;
    else sta = 2;
    Circle c2 = Circle(p2, sqrt(max(0.0, norm(tmp) - c1.r * c1.r)));
    cc_cross(c1, c2, ans);
    return sta;
}

int tangent(Circle c1, Circle c2, vector<Line> &ans) { //圆和点切线
    ans.clear();
    if (sgn(c1.r - c2.r) < 0) swap(c1, c2);
    double g = norm(c1.o - c2.o);
    if (sgn(g) == 0) return 0;
    Point u = (c2.o - c1.o) / sqrt(g);
    Point v = orth(u);
    for (int s = 1; s >= -1; s -= 2) {
        double h = (c1.r + s * c2.r) / sqrt(g);
        if (sgn(1 - h * h) == 0) {
            ans.push_back(Line(c1.o + u * c1.r, c1.o + (u + v) * c1.r));
        } else if (sgn(1 - h * h) >= 0) {
            Point uu = u * h, vv = v * sqrt(1 - h * h);
            ans.push_back(Line(c1.o + (uu + vv) * c1.r, c2.o - (uu + vv) * c2.r * s));
            ans.push_back(Line(c1.o + (uu - vv) * c1.r, c2.o - (uu - vv) * c2.r * s));
        }
    }

    return ans.size();
}

double areaofCC(Circle c1, Circle c2) { //两圆面积交
    if (c1.r > c2.r) swap(c1, c2);
    double nor = norm(c1.o - c2.o);
    double dist = sqrt(max(0.0, nor));

    if (sgn(c1.r + c2.r - dist) <= 0) return 0;

    if (sgn(dist + c1.r - c2.r) <= 0) return c1.r * c1.r * PI;

    double val;
    val = (nor + c1.r * c1.r - c2.r * c2.r) / (2 * c1.r * dist);
    val = max(val, -1.0), val = min(val, 1.0);
    double theta1 = acos(val);
    val = (nor + c2.r * c2.r - c1.r * c1.r) / (2 * c2.r * dist);
    val = max(val, -1.0), val = min(val, 1.0);
    double theta2 = acos(val);
    return (theta1 - sin(theta1 + theta1) * 0.5) * c1.r * c1.r + (theta2 - sin(theta2 + theta2) * 0.5) * c2.r * c2.r;
}


int convexCut(Point *p, Point *ans, int n, Line l) {
    int top = 0;
    for (int i = 0; i < n; i++) {
        Point a = p[i], b = p[(i + 1) % n];
        if (ccw(l.s, l.t, a) != -1) ans[top++] = a;
        if (ccw(l.s, l.t, a) * ccw(l.s, l.t, b) < 0)
            ans[top++] = ll_intersection(Line(a, b), l);
    }
    return top;
}

Point p[N];
Point ans[N];
Point ct[N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> p[i];
    int k = andrew(p, ans, n);
    int q;
    cin >> q;
    while (q--) {
        Line l;
        cin >> l.s >> l.t;
        int top = convexCut(ans, ct, k, l);
        cout << fixed << setprecision(10) << area(ct, top) << endl;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 112728
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1e6 + 10;

const double eps = 1e-9;
const double PI = acos(-1.0);
const double dinf = 1e99;
const ll inf = 0x3f3f3f3f3f3f3f3f;
struct Line;

struct Point {
    double x, y;

    Point() { x = y = 0; }

    Point(const Line &a);

    Point(const double &a, const double &b) : x(a), y(b) {}

    Point operator+(const Point &a) const {
        return {x + a.x, y + a.y};
    }

    Point operator-(const Point &a) const {
        return {x - a.x, y - a.y};
    }

    Point operator*(const double &a) const {
        return {x * a, y * a};
    }

    Point operator/(const double &d) const {
        return {x / d, y / d};
    }

    bool operator==(const Point &a) const {
        return abs(x - a.x) + abs(y - a.y) < eps;
    }

    void standardize() {
        *this = *this / sqrt(x * x + y * y);
    }
};

double norm(const Point &p) { return p.x * p.x + p.y * p.y; }

Point orth(const Point &a) { return Point(-a.y, a.x); }

double dist(const Point &a, const Point &b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

double dist2(const Point &a, const Point &b) {
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

struct Line {
    Point s, t;

    Line() {}

    Line(const Point &a, const Point &b) : s(a), t(b) {}

};


struct Circle {
    Point o;
    double r;

    Circle() {}

    Circle(Point P, double R = 0) { o = P, r = R; }
};

double length(const Point &p) {
    return sqrt(p.x * p.x + p.y * p.y);
}

double length(const Line &l) {
    Point p(l);
    return length(p);
}

Point::Point(const Line &a) { *this = a.t - a.s; }

istream &operator>>(istream &in, Point &a) {
    in >> a.x >> a.y;
    return in;
}

ostream &operator<<(ostream &out, Point &a) {
    out << fixed << setprecision(10) << a.x << ' ' << a.y;
    return out;
}

double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }

double det(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }

int sgn(const double &x) { return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1); }

double sqr(const double &x) { return x * x; }

Point rotate(const Point &a, const double &ang) {
    double x = cos(ang) * a.x - sin(ang) * a.y;
    double y = sin(ang) * a.x + cos(ang) * a.y;
    return {x, y};
}

//点在线段上 <=0 包含端点
bool sp_on(const Line &seg, const Point &p) {
    Point a = seg.s, b = seg.t;
    return !sgn(det(p - a, b - a)) && sgn(dot(p - a, p - b)) <= 0;
}

bool lp_on(const Line &line, const Point &p) {
    Point a = line.s, b = line.t;
    return !sgn(det(p - a, b - a));
}

//等于不包含共线
int andrew(Point *point, Point *convex, int n) {
    sort(point, point + n, [](Point a, Point b) {
        if (a.x != b.x) return a.x < b.x;
        return a.y < b.y;
    });
    int top = 0;
    for (int i = 0; i < n; i++) {
        while ((top > 1) && det(convex[top - 1] - convex[top - 2], point[i] - convex[top - 1]) <= 0)
            top--;
        convex[top++] = point[i];
    }
    int tmp = top;
    for (int i = n - 2; i >= 0; i--) {
        while ((top > tmp) && det(convex[top - 1] - convex[top - 2], point[i] - convex[top - 1]) <= 0)
            top--;
        convex[top++] = point[i];
    }
    if (n > 1) top--;
    return top;
}

double slope(const Point &a, const Point &b) { return (a.y - b.y) / (a.x - b.x); }

double slope(const Line &a) { return slope(a.s, a.t); }

Point ll_intersection(const Line &a, const Line &b) {
    double s1 = det(Point(a), b.s - a.s), s2 = det(Point(a), b.t - a.s);
    return (b.s * s2 - b.t * s1) / (s2 - s1);
}

int ss_cross(const Line &a, const Line &b, Point &p) {
    int d1 = sgn(det(a.t - a.s, b.s - a.s));
    int d2 = sgn(det(a.t - a.s, b.t - a.s));
    int d3 = sgn(det(b.t - b.s, a.s - b.s));
    int d4 = sgn(det(b.t - b.s, a.t - b.s));
    if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2) {
        p = ll_intersection(a, b);
        return 1;
    }
    if (!d1 && sp_on(a, b.s)) {
        p = b.s;
        return 2;
    }
    if (!d2 && sp_on(a, b.t)) {
        p = b.t;
        return 2;
    }
    if (!d3 && sp_on(b, a.s)) {
        p = a.s;
        return 2;
    }
    if (!d4 && sp_on(b, a.t)) {
        p = a.t;
        return 2;
    }
    return 0;
}


int ccw(const Point &a, Point b, Point c) {
    b = b - a, c = c - a;
    if (sgn(det(b, c)) > 0) return +1;  // "COUNTER_CLOCKWISE"
    if (sgn(det(b, c)) < 0) return -1; // "CLOCKWISE"
    if (sgn(dot(b, c)) < 0) return +2;      // "ONLINE_BACK"
    if (sgn(norm(b) - norm(c)) < 0) return -2;  // "ONLINE_FRONT"
    return 0;                         // "ON_SEGMENT"
}


Point project(const Line &l, const Point &p) {
    Point base(l);
    double r = dot(base, p - l.s) / sqr(length(base));
    return l.s + (base * r);
}

double sp_dist(const Line &l, const Point &p) {
    if (l.s == l.t) return dist(l.s, p);
    Point x = p - l.s, y = p - l.t, z = l.t - l.s;
    if (sgn(dot(x, z)) < 0)return length(x);//P距离A更近
    if (sgn(dot(y, z)) > 0)return length(y);//P距离B更近
    return abs(det(x, z) / length(z));//面积除以底边长
}

double lp_dist(const Line &l, const Point &p) {
    Point x = p - l.s, y = p - l.t, z = l.t - l.s;
    return abs(det(x, z) / length(z));//面积除以底边长
}

int cl_cross(const Circle &c, const Line &l, pair<Point, Point> &ans) {
    Point a = c.o;
    double r = c.r;
    Point pr = project(l, a);
    double dis = dist(pr, a);
    double tmp = r * r - dis * dis;
    if (sgn(tmp) == 1) {
        double base = sqrt(max(0.0, r * r - dis * dis));
        Point e(l);
        e.standardize();
        e = e * base;
        ans = make_pair(pr + e, pr - e);
        return 2;
    } else if (sgn(tmp) == 0) {
        ans = make_pair(pr, pr);
        return 1;
    } else return 0;
}

int intersectCS(Circle c, Line l) {//交点个数，下面cs_cross用到
    if (sgn(norm(project(l, c.o) - c.o) - c.r * c.r) > 0) return 0;
    double d1 = length(c.o - l.s), d2 = length(c.o - l.t);
    if (sgn(d1 - c.r) <= 0 && sgn(d2 - c.r) <= 0) return 0;
    if ((sgn(d1 - c.r) < 0 && sgn(d2 - c.r) > 0) || (sgn(d1 - c.r) > 0 && sgn(d2 - c.r) < 0)) return 1;
    Point h = project(l, c.o);
    if (dot(l.s - h, l.t - h) < 0) return 2;
    return 0;
}

int cs_cross(Circle c, Line s, pair<Point, Point> &ans) {//圆和线段交点
    Line l(s);
    int num = cl_cross(c, l, ans);
    int res = intersectCS(c, s);
    if (res == 2) return 2;
    if (num > 1) {
        if (dot(l.s - ans.first, l.t - ans.first) > 0) swap(ans.first, ans.second);
        ans.second = ans.first;
    }
    return res;
}


int cc_cross(const Circle &cir1, const Circle &cir2, pair<Point, Point> &ans) {
    const Point &c1 = cir1.o, &c2 = cir2.o;
    const double &r1 = cir1.r, &r2 = cir2.r;
    double x1 = c1.x, x2 = c2.x, y1 = c1.y, y2 = c2.y;
    double d = length(c1 - c2);
    if (sgn(fabs(r1 - r2) - d) > 0) return 0;  //内含
    if (sgn(r1 + r2 - d) < 0) return 4; //相离
    double a = r1 * (x1 - x2) * 2, b = r1 * (y1 - y2) * 2, c = r2 * r2 - r1 * r1 - d * d;
    double p = a * a + b * b, q = -a * c * 2, r = c * c - b * b;

    double cosa, sina, cosb, sinb;
    //One Intersection
    if (sgn(d - (r1 + r2)) == 0 || sgn(d - fabs(r1 - r2)) == 0) {
        cosa = -q / p / 2;
        sina = sqrt(1 - sqr(cosa));
        Point p0(x1 + r1 * cosa, y1 + r1 * sina);
        if (sgn(dist(p0, c2) - r2)) p0.y = y1 - r1 * sina;
        ans = pair<Point, Point>(p0, p0);
        if (sgn(r1 + r2 - d) == 0) return 3;    //外切
        else return 1;  //内切
    }
    //Two Intersections
    double delta = sqrt(q * q - p * r * 4);
    cosa = (delta - q) / p / 2;
    cosb = (-delta - q) / p / 2;
    sina = sqrt(1 - sqr(cosa));
    sinb = sqrt(1 - sqr(cosb));
    Point p1(x1 + r1 * cosa, y1 + r1 * sina);
    Point p2(x1 + r1 * cosb, y1 + r1 * sinb);
    if (sgn(dist(p1, c2) - r2)) p1.y = y1 - r1 * sina;
    if (sgn(dist(p2, c2) - r2)) p2.y = y1 - r1 * sinb;
    if (p1 == p2) p1.y = y1 - r1 * sina;
    ans = pair<Point, Point>(p1, p2);
    return 2;   //  相交
}

Point lp_sym(const Line &l, const Point &p) {
    return p + (project(l, p) - p) * 2;
}

double alpha(const Point &t1, const Point &t2) {
    double theta;
    theta = atan2((double) t2.y, (double) t2.x) - atan2((double) t1.y, (double) t1.x);
    if (sgn(theta) < 0)
        theta += 2.0 * PI;
    return theta;
}

int pip(const Point *P, const int &n, const Point &a) {//【射线法】判断点A是否在任意多边形Poly以内
    int cnt = 0;
    double tmp;
    for (int i = 1; i <= n; ++i) {
        int j = i < n ? i + 1 : 1;
        if (sp_on(Line(P[i], P[j]), a))return 2;//点在多边形上
        if (a.y >= min(P[i].y, P[j].y) && a.y < max(P[i].y, P[j].y))//纵坐标在该线段两端点之间
            tmp = P[i].x + (a.y - P[i].y) / (P[j].y - P[i].y) * (P[j].x - P[i].x), cnt += sgn(tmp - a.x) > 0;//交点在A右方
    }
    return cnt & 1;//穿过奇数次则在多边形以内
}

bool pip_convex_jud(const Point &a, const Point &L, const Point &R) {//判断AL是否在AR右边
    return sgn(det(L - a, R - a)) > 0;//必须严格以内
}

bool pip_convex(const Point *P, const int &n, const Point &a) {//【二分法】判断点A是否在凸多边形Poly以内
    //点按逆时针给出
    if (pip_convex_jud(P[0], a, P[1]) || pip_convex_jud(P[0], P[n - 1], a)) return 0;//在P[0_1]或P[0_n-1]外
    if (sp_on(Line(P[0], P[1]), a) || sp_on(Line(P[0], P[n - 1]), a)) return 2;//在P[0_1]或P[0_n-1]上
    int l = 1, r = n - 2;
    while (l < r) {//二分找到一个位置pos使得P[0]_A在P[0_pos],P[0_(pos+1)]之间
        int mid = (l + r + 1) >> 1;
        if (pip_convex_jud(P[0], P[mid], a))l = mid;
        else r = mid - 1;
    }
    if (pip_convex_jud(P[l], a, P[l + 1]))return 0;//在P[pos_(pos+1)]外
    if (sp_on(Line(P[l], P[l + 1]), a))return 2;//在P[pos_(pos+1)]上
    return 1;
}
// 多边形是否包含线段
// 因此我们可以先求出所有和线段相交的多边形的顶点，然后按照X-Y坐标排序(X坐标小的排在前面，对于X坐标相同的点，Y坐标小的排在前面，
// 这种排序准则也是为了保证水平和垂直情况的判断正确)，这样相邻的两个点就是在线段上相邻的两交点，如果任意相邻两点的中点也在多边形内，
// 则该线段一定在多边形内。

int pp_judge(Point *A, int n, Point *B, int m) {//【判断多边形A与多边形B是否相离】
    for (int i1 = 1; i1 <= n; ++i1) {
        int j1 = i1 < n ? i1 + 1 : 1;
        for (int i2 = 1; i2 <= m; ++i2) {
            int j2 = i2 < m ? i2 + 1 : 1;
            Point tmp;
            if (ss_cross(Line(A[i1], A[j1]), Line(B[i2], B[j2]), tmp)) return 0;//两线段相交
            if (pip(B, m, A[i1]) || pip(A, n, B[i2]))return 0;//点包含在内
        }
    }
    return 1;
}

double area(Point *P, int n) {//【任意多边形P的面积】
    double S = 0;
    for (int i = 0; i < n; i++) S += det(P[i], P[(i + 1) % n]);
    return S * 0.5;
}

double pc_area(Point *p, int n, const Circle &c) {
    if (n < 3) return 0;
    function<double(Circle, Point, Point)> dfs = [&](Circle c, Point a, Point b) {
        Point va = c.o - a, vb = c.o - b;
        double f = det(va, vb), res = 0;
        if (sgn(f) == 0) return res;
        if (sgn(max(length(va), length(vb)) - c.r) <= 0) return f;
        Point d(dot(va, vb), det(va, vb));
        if (sgn(sp_dist(Line(a, b), c.o) - c.r) >= 0) return c.r * c.r * atan2(d.y, d.x);
        pair<Point, Point> u;
        int cnt = cs_cross(c, Line(a, b), u);
        if (cnt == 0) return res;
        if (cnt > 1 && sgn(dot(u.second - u.first, a - u.first)) > 0) swap(u.first, u.second);
        res += dfs(c, a, u.first);
        if (cnt == 2) res += dfs(c, u.first, u.second) + dfs(c, u.second, b);
        else if (cnt == 1) res += dfs(c, u.first, b);
        return res;
    };
    double res = 0;
    for (int i = 0; i < n; i++) {
        res += dfs(c, p[i], p[(i + 1) % n]);
    }
    return res * 0.5;
}

Line Q[N];

int judge(Line L, Point a) { return sgn(det(a - L.s, L.t - L.s)) > 0; }//判断点a是否在直线L的右边
int halfcut(Line *L, int n, Point *P) {//【半平面交】
    sort(L, L + n, [](const Line &a, const Line &b) {
        double d = atan2((a.t - a.s).y, (a.t - a.s).x) - atan2((b.t - b.s).y, (b.t - b.s).x);
        return sgn(d) ? sgn(d) < 0 : judge(a, b.s);
    });

    int m = n;
    n = 0;
    for (int i = 0; i < m; ++i)
        if (i == 0 || sgn(atan2(Point(L[i]).y, Point(L[i]).x) - atan2(Point(L[i - 1]).y, Point(L[i - 1]).x)))
            L[n++] = L[i];
    int h = 1, t = 0;
    for (int i = 0; i < n; ++i) {
        while (h < t && judge(L[i], ll_intersection(Q[t], Q[t - 1]))) --t;//当队尾两个直线交点不是在直线L[i]上或者左边时就出队
        while (h < t && judge(L[i], ll_intersection(Q[h], Q[h + 1]))) ++h;//当队头两个直线交点不是在直线L[i]上或者左边时就出队
        Q[++t] = L[i];

    }
    while (h < t && judge(Q[h], ll_intersection(Q[t], Q[t - 1]))) --t;
    while (h < t && judge(Q[t], ll_intersection(Q[h], Q[h + 1]))) ++h;
    n = 0;
    for (int i = h; i <= t; ++i) {
        P[n++] = ll_intersection(Q[i], Q[i < t ? i + 1 : h]);
    }
    return n;
}

Point V1[N], V2[N];

int mincowski(Point *P1, int n, Point *P2, int m, Point *V) {//【闵可夫斯基和】求两个凸包{P1},{P2}的向量集合{V}={P1+P2}构成的凸包
    for (int i = 0; i < n; ++i) V1[i] = P1[(i + 1) % n] - P1[i];
    for (int i = 0; i < m; ++i) V2[i] = P2[(i + 1) % m] - P2[i];
    int t = 0, i = 0, j = 0;
    V[t++] = P1[0] + P2[0];
    while (i < n && j < m) V[t] = V[t - 1] + (sgn(det(V1[i], V2[j])) > 0 ? V1[i++] : V2[j++]), t++;
    while (i < n) V[t] = V[t - 1] + V1[i++], t++;
    while (j < m) V[t] = V[t - 1] + V2[j++], t++;
    return t;
}

Circle external_circle(const Point &A, const Point &B, const Point &C) {//【三点确定一圆】向量垂心法
    Point P1 = (A + B) * 0.5, P2 = (A + C) * 0.5;
    Line R1 = Line(P1, P1 + orth(B - A));
    Line R2 = Line(P2, P2 + orth(C - A));
    Circle O;
    O.o = ll_intersection(R1, R2);
    O.r = length(A - O.o);
    return O;
}

Circle internal_circle(const Point &A, const Point &B, const Point &C) {
    double a = dist(B, C), b = dist(A, C), c = dist(A, B);
    double s = (a + b + c) / 2;
    double S = sqrt(max(0.0, s * (s - a) * (s - b) * (s - c)));
    double r = S / s;

    return Circle((A * a + B * b + C * c) / (a + b + c), r);
}


struct ConvexHull {

    int op;

    struct cmp {
        bool operator()(const Point &a, const Point &b) const {
            return sgn(a.x - b.x) < 0 || sgn(a.x - b.x) == 0 && sgn(a.y - b.y) < 0;
        }
    };

    set<Point, cmp> s;

    ConvexHull(int o) {
        op = o;
        s.clear();
    }

    inline int PIP(Point P) {
        set<Point>::iterator it = s.lower_bound(Point(P.x, -dinf));//找到第一个横坐标大于P的点
        if (it == s.end())return 0;
        if (sgn(it->x - P.x) == 0) return sgn((P.y - it->y) * op) <= 0;//比较纵坐标大小
        if (it == s.begin())return 0;
        set<Point>::iterator j = it, k = it;
        --j;
        return sgn(det(P - *j, *k - *j) * op) >= 0;//看叉姬1
    }

    inline int judge(set<Point>::iterator it) {
        set<Point>::iterator j = it, k = it;
        if (j == s.begin())return 0;
        --j;
        if (++k == s.end())return 0;
        return sgn(det(*it - *j, *k - *j) * op) >= 0;//看叉姬
    }

    inline void insert(Point P) {
        if (PIP(P))return;//如果点P已经在凸壳上或凸包里就不插入了
        set<Point>::iterator tmp = s.lower_bound(Point(P.x, -dinf));
        if (tmp != s.end() && sgn(tmp->x - P.x) == 0)s.erase(tmp);//特判横坐标相等的点要去掉
        s.insert(P);
        set<Point>::iterator it = s.find(P), p = it;
        if (p != s.begin()) {
            --p;
            while (judge(p)) {
                set<Point>::iterator temp = p--;
                s.erase(temp);
            }
        }
        if ((p = ++it) != s.end()) {
            while (judge(p)) {
                set<Point>::iterator temp = p++;
                s.erase(temp);
            }
        }
    }
} up(1), down(-1);

int PIC(Circle C, Point a) { return sgn(length(a - C.o) - C.r) <= 0; }//判断点A是否在圆C内
void Random(Point *P, int n) { for (int i = 0; i < n; ++i)swap(P[i], P[(rand() + 1) % n]); }//随机一个排列
Circle min_circle(Point *P, int n) {//【求点集P的最小覆盖圆】 O(n)
//  random_shuffle(P,P+n);
    Random(P, n);
    Circle C = Circle(P[0], 0);
    for (int i = 1; i < n; ++i)
        if (!PIC(C, P[i])) {
            C = Circle(P[i], 0);
            for (int j = 0; j < i; ++j)
                if (!PIC(C, P[j])) {
                    C.o = (P[i] + P[j]) * 0.5, C.r = length(P[j] - C.o);
                    for (int k = 0; k < j; ++k) if (!PIC(C, P[k])) C = external_circle(P[i], P[j], P[k]);
                }
        }
    return C;
}


int temp[N];

double closest_point(Point *p, int n) {
    function<double(int, int)> merge = [&](int l, int r) {
        double d = dinf;
        if (l == r) return d;
        if (l + 1 == r) return dist(p[l], p[r]);
        int mid = (l + r) >> 1;
        double d1 = merge(l, mid);
        double d2 = merge(mid + 1, r);
        d = min(d1, d2);
        int i, j, k = 0;
        for (i = l; i <= r; i++) {
            if (sgn(abs(p[mid].x - p[i].x) - d) <= 0)
                temp[k++] = i;

        }
        sort(temp, temp + k, [&](const int &a, const int &b) {
            return sgn(p[a].y - p[b].y) < 0;
        });
        for (i = 0; i < k; i++) {
            for (j = i + 1; j < k && sgn(p[temp[j]].y - p[temp[i]].y - d) <= 0; j++) {
                double d3 = dist(p[temp[i]], p[temp[j]]);
                d = min(d, d3);
            }
        }
        return d;
    };
    sort(p, p + n, [&](const Point &a, const Point &b) {
        if (sgn(a.x - b.x) == 0) return sgn(a.y - b.y) < 0;
        else return sgn(a.x - b.x) < 0;
    });
    return merge(0, n - 1);
}

int tangent(const Circle &c1, const Point &p2, pair<Point, Point> &ans) { //圆和点切线
    Point tmp = c1.o - p2;
    int sta;
    if (sgn(norm(tmp) - c1.r * c1.r) < 0) return 0;
    else if (sgn(norm(tmp) - c1.r * c1.r) == 0) sta = 1;
    else sta = 2;
    Circle c2 = Circle(p2, sqrt(max(0.0, norm(tmp) - c1.r * c1.r)));
    cc_cross(c1, c2, ans);
    return sta;
}

int tangent(Circle c1, Circle c2, vector<Line> &ans) { //圆和点切线
    ans.clear();
    if (sgn(c1.r - c2.r) < 0) swap(c1, c2);
    double g = norm(c1.o - c2.o);
    if (sgn(g) == 0) return 0;
    Point u = (c2.o - c1.o) / sqrt(g);
    Point v = orth(u);
    for (int s = 1; s >= -1; s -= 2) {
        double h = (c1.r + s * c2.r) / sqrt(g);
        if (sgn(1 - h * h) == 0) {
            ans.push_back(Line(c1.o + u * c1.r, c1.o + (u + v) * c1.r));
        } else if (sgn(1 - h * h) >= 0) {
            Point uu = u * h, vv = v * sqrt(1 - h * h);
            ans.push_back(Line(c1.o + (uu + vv) * c1.r, c2.o - (uu + vv) * c2.r * s));
            ans.push_back(Line(c1.o + (uu - vv) * c1.r, c2.o - (uu - vv) * c2.r * s));
        }
    }

    return ans.size();
}

double areaofCC(Circle c1, Circle c2) { //两圆面积交
    if (c1.r > c2.r) swap(c1, c2);
    double nor = norm(c1.o - c2.o);
    double dist = sqrt(max(0.0, nor));

    if (sgn(c1.r + c2.r - dist) <= 0) return 0;

    if (sgn(dist + c1.r - c2.r) <= 0) return c1.r * c1.r * PI;

    double val;
    val = (nor + c1.r * c1.r - c2.r * c2.r) / (2 * c1.r * dist);
    val = max(val, -1.0), val = min(val, 1.0);
    double theta1 = acos(val);
    val = (nor + c2.r * c2.r - c1.r * c1.r) / (2 * c2.r * dist);
    val = max(val, -1.0), val = min(val, 1.0);
    double theta2 = acos(val);
    return (theta1 - sin(theta1 + theta1) * 0.5) * c1.r * c1.r + (theta2 - sin(theta2 + theta2) * 0.5) * c2.r * c2.r;
}


int convexCut(Point *p, Point *ans, int n, Line l) {
    int top = 0;
    for (int i = 0; i < n; i++) {
        Point a = p[i], b = p[(i + 1) % n];
        if (ccw(l.s, l.t, a) != -1) ans[top++] = a;
        if (ccw(l.s, l.t, a) * ccw(l.s, l.t, b) < 0)
            ans[top++] = ll_intersection(Line(a, b), l);
    }
    return top;
}

Point p[N];
Point ans[N];
Point ct[N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> p[i];
    int k = andrew(p, ans, n);
    int q;
    cin >> q;
    while (q--) {
        Line l;
        cin >> l.s >> l.t;
        int top = convexCut(ans, ct, k, l);
        cout << fixed << setprecision(10) << area(ct, top) << endl;
    }
}
accuracy: 0.375
time_ms: 20
memory_kb: 112676
final_rank: 4