Problem:
E: Do You Divide It? / 切り刻む気か？
物語
T君は過去に出場したプログラミングコンテストで平面図形の問題にひどく手こずらされ，それ以来，平面図形に強い恨みを抱いている．
中でも，特に二次元平面上に描かれる多角形に対して複雑な感情を抱いているため，多角形を見かけると切り刻まずにはいられない．
T君が多角形を切り刻むときには，y軸に平行に幅
0.5
の間隔でスリットの入った板で多角形を覆い，スリットで見えない部分を切り刻んで捨ててしまう．
しかしながら，T君は一方的な殺戮を好まないため，多角形に再起の芽を残すべく，切り刻んだ後に残る図形の合計面積ができるだけ大きくなるように配慮する．
T君が切り刻んだ後に残る図形の面積を求めよう．
問題
二次元平面にy軸方向無限長のスリットが入っており，x軸方向に
0.5
ごとに見える部分と見えない部分が切り替わるようになっている．
下図のように，この平面上で，
N
個の頂点からなる多角形がx軸正方向に向けて平行移動し続ける．
多角形が見える部分が最も大きくなる瞬間の，見えている部分の面積を出力せよ．
入力形式
1
行目で
N
を与える．続く
N
行の
i
行目で，多角形の反時計回りでの
i
番目の頂点座標(
x_i
,
y_i
)を与える．
以下を仮定してよい．
入力はすべて整数
3 ≤ N ≤ 100
,
−10^3 ≤ x_i, y_i ≤ 10^3
与えられる多角形は，隣接する線分以外と辺や頂点を共有することはない
与えられる多角形の連続する3つの頂点は同一直線上にない
出力形式
与えられた多角形の見える部分が最も大きくなる瞬間の，見える面積を
1
行で出力せよ．
絶対誤差，相対誤差は
10^{−5}
まで許容する．
入力例1
6
0 0
-1 -2
3 -2
2 0
3 2
-1 2
出力例1
6.000000000
入力例2
5
0 0
2 -2
4 -2
4 2
2 2
出力例2
6.50000000

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001




#define EPS2 0.001
#define SIZE 105

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct IntPoint{
	IntPoint(int arg_x,int arg_y){
		x = arg_x;
		y = arg_y;
	}

	IntPoint(){
		x = y = 0;
	}



	bool operator<(const IntPoint &p) const{

		if(x != p.x){

			return x < p.x;

		}else{

			return y < p.y;
		}
	}

	bool operator == (const IntPoint &p) const{
		return (x == p.x) && (y == p.y);
	}

	void outPut(){

		printf("%d %d\n",x,y);
	}

	int x,y;
};

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//■■直線ではなく、線分の交差判定■■
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


int main(){

	int N;
	scanf("%d",&N);


	Polygon poly;
	vector<IntPoint> POLY;

	int x,y;
	int x_min = BIG_NUM,x_max = -BIG_NUM;

	for(int i = 0; i < N; i++){

		scanf("%d %d",&x,&y);
		poly.push_back(Point(x,y));
		POLY.push_back(IntPoint(x,y));

		chmin(x_min,x);
		chmax(x_max,x);
	}

	vector<Line> LINE;

	for(int i = 0; i < N; i++){

		Point a = poly[i];
		Point b = poly[(i+1)%N];
		LINE.push_back(Line(a,b));
	}

	double S = calc_S(poly);

	double sum = 0;
	const double H = 0.5;

	for(int x = x_min; x <= x_max-1; x += 1){

		vector<double> left,right;
		Line line_L = Line(Point(x,BIG_NUM),Point(x,-BIG_NUM));
		Line line_R = Line(Point(x+0.5,BIG_NUM),Point(x+0.5,-BIG_NUM));

		for(int i = 0; i < N; i++){

			IntPoint a = POLY[i];
			IntPoint b = POLY[(i+1)%N];

			if((a.x <= x && b.x <= x) || (a.x > x && b.x > x))continue;

			Point cross_l = calc_Cross_Point(LINE[i],line_L);
			left.push_back(cross_l.y);

			Point cross_r = calc_Cross_Point(LINE[i],line_R);
			right.push_back(cross_r.y);
		}

		sort(left.begin(),left.end());
		sort(right.begin(),right.end());

		for(int i = 0; i < left.size(); i += 2){

			double joutei = left[i+1]-left[i];
			double katei = right[i+1]-right[i];

			sum += (joutei+katei)*H/2;
		}
	}

	printf("%.10lf\n",max(sum,S-sum));

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3256
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001




#define EPS2 0.001
#define SIZE 105

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct IntPoint{
	IntPoint(int arg_x,int arg_y){
		x = arg_x;
		y = arg_y;
	}

	IntPoint(){
		x = y = 0;
	}



	bool operator<(const IntPoint &p) const{

		if(x != p.x){

			return x < p.x;

		}else{

			return y < p.y;
		}
	}

	bool operator == (const IntPoint &p) const{
		return (x == p.x) && (y == p.y);
	}

	void outPut(){

		printf("%d %d\n",x,y);
	}

	int x,y;
};

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//■■直線ではなく、線分の交差判定■■
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}


bool DEBUG = false;



int main(){

	int N;
	scanf("%d",&N);


	Polygon poly;
	vector<IntPoint> POLY;

	int x,y;
	int x_min = BIG_NUM,x_max = -BIG_NUM;

	for(int i = 0; i < N; i++){

		scanf("%d %d",&x,&y);
		poly.push_back(Point(x,y));
		POLY.push_back(IntPoint(x,y));

		chmin(x_min,x);
		chmax(x_max,x);
	}

	vector<Line> LINE;

	for(int i = 0; i < N; i++){

		Point a = poly[i];
		Point b = poly[(i+1)%N];
		LINE.push_back(Line(a,b));
	}

	double S = calc_S(poly);

	double sum = 0;
	const double H = 0.5;

	for(int x = x_min; x <= x_max-1; x += 1){

		vector<double> left,right;
		Line line_L = Line(Point(x,BIG_NUM),Point(x,-BIG_NUM));
		Line line_R = Line(Point(x+0.5,BIG_NUM),Point(x+0.5,-BIG_NUM));

		for(int i = 0; i < N; i++){

			IntPoint a = POLY[i];
			IntPoint b = POLY[(i+1)%N];

			if((a.x <= x && b.x <= x) || (a.x > x && b.x > x))continue;

			Point cross_l = calc_Cross_Point(LINE[i],line_L);
			left.push_back(cross_l.y);

			Point cross_r = calc_Cross_Point(LINE[i],line_R);
			right.push_back(cross_r.y);
		}

		sort(left.begin(),left.end());
		sort(right.begin(),right.end());

		for(int i = 0; i < left.size(); i += 2){

			double joutei = left[i+1]-left[i];
			double katei = right[i+1]-right[i];

			sum += (joutei+katei)*H/2;
		}
	}

	//printf("S:%.3lf sum:%.3lf\n",S,sum);

	printf("%.10lf\n",max(sum,S-sum));

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3256
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001




#define EPS2 0.001
#define SIZE 105

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//■■直線ではなく、線分の交差判定■■
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}


bool DEBUG = false;

vector<double> calc(double x,vector<Line> LINE,Polygon poly){

	Line tmp_line = Line(Point(x,BIG_NUM),Point(x,-BIG_NUM));

	vector<double> ret;

	for(int i = 0; i < LINE.size(); i++){

		if(!is_Cross(tmp_line,LINE[i]))continue;

		if(DEBUG){
		LINE[i].outPut();
		}

		Point cross_p = calc_Cross_Point(tmp_line,LINE[i]);


		ret.push_back(cross_p.y);
	}

	sort(ret.rbegin(),ret.rend());
	ret.erase(unique(ret.begin(),ret.end()),ret.end());

	return ret;
}


//区切る必要があるか
bool Check(Point p,Polygon poly){

	p.x += EPS2;

	return contains(poly,p) == 0;
}


int main(){

	int N;
	scanf("%d",&N);


	Polygon poly;

	int x,y;
	int x_min = BIG_NUM,x_max = -BIG_NUM;

	for(int i = 0; i < N; i++){

		scanf("%d %d",&x,&y);
		poly.push_back(Point(x,y));

		chmin(x_min,x);
		chmax(x_max,x);
	}

	vector<Line> LINE;

	for(int i = 0; i < N; i++){

		Point a = poly[i];
		Point b = poly[(i+1)%N];
		LINE.push_back(Line(a,b));
	}

	double S = calc_S(poly);

	double sum = 0;
	const double H = 0.5;

	for(int x = x_min; x <= x_max-1; x += 1){

		vector<double> left = calc(x,LINE,poly);
		vector<double> right = calc(x+0.5,LINE,poly);

		//printf("\nx:%d left.size():%lld right.size():%lld\n",x,left.size(),right.size());

		int l = 0,r = 0;

		while(l < left.size() && r < right.size()){

			if(l+1 == left.size()){ //点

				sum += (right[r]-right[r+1])*H/2;

				break;
			}

			Point mid_p = Point(x,(left[l]+left[l+1])/2);

			if(contains(poly,mid_p) == 0){ //点

				sum += (right[r]-right[r+1])*H/2;
				l++;
				r += 2;
				continue;
			}

			double joutei = left[l]-left[l+1];
			double katei = right[r]-right[r+1];
			l += 1;
			r += 2;

			while(!Check(Point(x,left[l]),poly) && l+1 < left.size()){

				mid_p = Point(x,(left[l]+left[l+1])/2);
				if(contains(poly,mid_p) == 0){

					break;
				}
				joutei += left[l]-left[l+1];
				l++;
			}

			sum += (joutei+katei)*H/2;
		}
	}

	//printf("S:%.3lf sum:%.3lf\n",S,sum);

	printf("%.10lf\n",max(sum,S-sum));

	return 0;
}
accuracy: 0.02040816326530612
time_ms: 110
memory_kb: 3504
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001




#define SIZE 105

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

int num_ignore = 0,numOne = 0;
Point to_ignore[SIZE],point_one[SIZE];
bool isOne[SIZE];


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//■■直線ではなく、線分の交差判定■■
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

bool checkIgnore(Point p){

	for(int i = 0; i < num_ignore; i++){
		if(p == to_ignore[i]){

			return true;
		}
	}
	return false;
}

int checkOne(Point p){

	int ret = -1;

	for(int i = 0; i < numOne; i++){
		if(p == point_one[i]){

			return i;
		}
	}
	return ret;
}

vector<double> calc(double x,vector<Line> LINE,Polygon poly){

	Line tmp_line = Line(Point(x,BIG_NUM),Point(x,-BIG_NUM));

	vector<double> ret;
	set<int> SET;

	for(int i = 0; i < LINE.size(); i++){

		if(!is_Cross(tmp_line,LINE[i]))continue;

		Point cross_p = calc_Cross_Point(tmp_line,LINE[i]);
		if(checkIgnore(cross_p))continue;
		int ind = checkOne(cross_p);

		if(ind != -1){

			SET.insert(ind);
			continue;
		}

		ret.push_back(cross_p.y);
	}

	for(int ind: SET){ //1個入れれば良い点のy座標をpush

		ret.push_back(point_one[ind].y);
	}

	sort(ret.rbegin(),ret.rend());

	return ret;
}


int main(){

	int N;
	scanf("%d",&N);


	Polygon poly;

	int x,y;
	int x_min = BIG_NUM,x_max = -BIG_NUM;

	for(int i = 0; i < N; i++){

		scanf("%d %d",&x,&y);
		poly.push_back(Point(x,y));

		chmin(x_min,x);
		chmax(x_max,x);
	}

	vector<Line> LINE;

	for(int i = 0; i < N; i++){

		Point a = poly[i];
		Point b = poly[(i+1)%N];
		LINE.push_back(Line(a,b));
	}

	//■特別扱いする交点を列挙
	for(int i = 0; i < N; i++){

		Point base = poly[i];
		Point pre = poly[(i-1+N)%N];
		Point next = poly[(i+1)%N];

		if(ccw(base,pre,next) == COUNTER_CLOCKWISE){

			Point p = base;
			p.x += 0.001;
			if(contains(poly,p) == 2){

				to_ignore[num_ignore++] = base; //無視
			}

		}else{

			Point p = base;
			p.y -= 0.001;

			if(contains(poly,p) != 0){

				point_one[numOne++] = base; //1個で良い
				continue;
			}

			p = base;
			p.y += 0.001;

			if(contains(poly,p) != 0){

				point_one[numOne++] = base; //1個で良い
				continue;
			}
		}
	}

	double S = calc_S(poly);

	double sum = 0;
	const double H = 0.5;

	for(int x = x_min; x <= x_max-1; x += 1){

		vector<double> left = calc(x,LINE,poly);
		vector<double> right = calc(x+0.5,LINE,poly);

		if(left.size() != right.size()){

			printf("left.size():%lld right.size():%lld\n",left.size(),right.size());
			return 0;
		}
		if(left.size()%2 == 1){

			printf("サイズが奇数 %lld\n",left.size());
			return 0;
		}

		//printf("\nx:%d left.size():%lld right.size():%lld\n",x,left.size(),right.size());

		for(int i = 0; i < left.size(); i += 2){

			double joutei = left[i]-left[i+1];
			double katei = right[i]-right[i+1];

			sum += (joutei+katei)*H/2.0;
		}
	}

	//printf("S:%.3lf sum:%.3lf\n",S,sum);

	printf("%.10lf\n",max(sum,S-sum));

	return 0;
}
accuracy: 0.20408163265306123
time_ms: 20
memory_kb: 3556
final_rank: 9

code_snippet: #include<bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define all(v) v.begin(), v.end()
using namespace std;
using ld = long double;
void fast_io(){ cout << fixed << setprecision(20); }

int main(){
    int n; cin >> n;
    vector<int> xs(n), ys(n);
    rep(i,n) cin >> xs[i] >> ys[i];
    rep(i,n){
        xs[i] += 1000, ys[i] += 1000;
        xs[i] *= 4, ys[i] *= 4;
    }
    const int mx = 8010;
    vector<vector<ld>> imos(mx);
    rep(i,n){
        int x1 = xs[i], y1 = ys[i];
        int x2 = xs[(i+1)%n], y2 = ys[(i+1)%n];
        if (x1 == x2) continue;
        if (x1 > x2) swap(x1,x2), swap(y1,y2);
        auto get = [&](int x){
            return ld(y2-y1) * ld(x-x1) / ld(x2-x1) + y1;
        };
        for (int x = x1+1; x <= x2-1; x += 2){
            imos[x].emplace_back(get(x));
        }
    }
    auto calc = [&](int i){
        ld ans = 0;
        for (int x = i; x < mx; x += 4){
            sort(all(imos[x]));
            int siz = imos[x].size();
            rep(k,siz/2){
                ans += imos[x][k*2+1] - imos[x][k*2];
            }
        }
        return ans;
    };
    ld ma = max(calc(1),calc(3));
    ma /= 8;
    fast_io();
    cout << ma << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 11740
final_rank: 6

code_snippet: #include <algorithm>
#include <iostream>
#include <complex>
#include <cstdio>
#include <cmath>
#include <utility>
#include <vector>
using namespace std;
using W = double;
using P = complex<W>;
using L = pair<P,P>;
using C = pair<P,W>;
using Poly = vector<P>;
#define X real()
#define Y imag()
const W EPS = (1e-10), pi = acos(-1);

double dot(P a, P b){ return a.X * b.X + a.Y * b.Y;}
W cross(P a, P b){ return a.X * b.Y - a.Y * b.X;}
P projection(P a, P b){ return dot(a, b)/abs(b)/abs(b)*b;}

//直線aと直線bの交点
P intersection(L a, L b){
  P af = a.first, as = a.second, bf = b.first, bs = b.second;
  return af + cross(bs-bf,af-bf)/(-cross(bs-bf,as-bf)+cross(bs-bf,af-bf))*(as-af);
}

//cがa/bと重なってる時は0を返す
//cがa/bと重なってる時+-2を返して欲しいなら+-2のところのEPSの符号を逆にする
int ccw(P a, P b, P c){
  b -= a; c -= a;
  if(cross(b,c) > EPS) return +1;
  if(cross(b,c) < -EPS) return -1;
  if(dot(b,c) < -EPS) return +2;
  if(norm(b) < norm(c)-EPS) return -2;
  return 0;
}

//凸多角形を直線で切る
//ccwが必要
Poly convex_cut(const Poly &p, L l){
  Poly ret;
  int n = p.size();
  for(int i = 0; i < n; ++i){
    P cur = p[i], nex = p[(i+1)%n], lf = l.first, ls = l.second;
    if(ccw(lf, ls, cur) != -1)
      ret.push_back(cur);
    if((ccw(lf, ls, cur) != -1) ^ (ccw(lf, ls, nex) != -1))
      ret.push_back(intersection(L(cur, nex), l));
  }
  return ret;
}

W area(const Poly &p){
  int n = p.size();
  W s = 0;
  for(int i = 0; i < n; ++i) s += cross(p[i],p[(i+1)%n])/2;
  return s;
}

int main(){
  int N;
  cin >> N;
  Poly pol;
  for(int i = 0; i < N; ++i){
    W x, y;
    cin >> x >> y;
    pol.emplace_back(x,y);
  }
  const W INF = 1e9;
  auto calc = [&](Poly t){
                W ret = 0;
                W l = min({0.0,t[1].X,t[2].X}), r = max({0.0,t[1].X,t[2].X});
                for(W x = l; x < r; x += 1){
                  Poly tt = convex_cut(t,L(P(x+0.5,-INF),P(x+0.5,INF)));
                  ret += area(tt);
                  t = convex_cut(t,L(P(x+1,INF),P(x+1,-INF)));
                }
                return abs(ret);
              };
  W s = 0;
  for(int i = 0; i < N; ++i){
    if(abs(P(0,0)-pol[i]) < EPS) continue;
    if(abs(P(0,0)-pol[(i+1)%N]) < EPS) continue;
    Poly t;
    t.push_back(P(0,0));
    t.push_back(pol[i]);
    t.push_back(pol[(i+1)%N]);
    W ds = calc(t);
    if(area(t) > 0) s += ds;
    else s -= ds;
  }
  W ans = max(s,area(pol)-s);
  printf("%.12f\n",ans);
}
accuracy: 1
time_ms: 50
memory_kb: 3344
final_rank: 5

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(dot(b,b-c) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}

int main(){
    int n;
    cin >> n;
    VP p(n);
    for(int i=0; i<n; i++){
        int x,y;
        cin >> x >> y;
        p[i] = P(x, y);
    }
    vector<double> area;
    const double dd = 0.5/4;
    for(double x=-1e3; x<1e3+EPS; x+=0.5){
        double len[2] = {0, 0};
        for(int d=0; d<2; d++){
            double xx = x +(1 +2*d)*dd;
            L cut(P(xx, -1e3), P(xx, 1e3));
            VP cp;
            for(int i=0; i<n; i++){
                L edge(p[i], p[(i+1)%n]);
                if(!isParallel(cut, edge) and intersectSS(cut, edge)){
                    cp.push_back(crosspointLL(cut, edge));
                }
            }
            sort(cp.begin(), cp.end());
            for(int i=0; i<(int)cp.size(); i+=2){
                len[d] += abs(cp[i+1] -cp[i]);
            }
        }
        double diff = (len[1]-len[0])/2;
        len[0] -= diff;
        len[1] += diff;
        area.push_back((len[0] +len[1])/4);
    }
    double s[2] = {0, 0};
    for(int i=0; i<(int)area.size(); i++){
        s[i%2] += area[i];
    }
    cout << fixed << setprecision(10);
    cout << max(s[0], s[1]) << endl;
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3380
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <map>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(dot(b,b-c) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}
bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}
double getarea(const VP &poly){
    double ret = 0;
    for (int i=0; i<(int)poly.size(); i++){ 
        ret += cross(poly[i], poly[(i+1)%poly.size()]);
    }
    return ret*0.5;
}
int in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int ret = -1;
    for(int i=0; i<n; i++){
        P a = poly[i]-p;
        P b = poly[(i+1)%n]-p;
        if(a.Y > b.Y) swap(a,b);
        if(intersectSP(L(a,b), P(0,0))) return 0;
        if(a.Y<=0 && b.Y>0 && cross(a,b)<0) ret = -ret;
    }
    return ret;
}

VP convex(VP v){
    VP ret;
    int n = v.size();
    sort(v.begin(), v.end());
    for(int i=0; i<n; i++){
        while((int)ret.size()>1 && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    int t = ret.size();
    for(int i=n-2; i>=0; i--){
        while((int)ret.size()>t && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    if((int)ret.size() > 1) ret.pop_back();
    return ret;
}
VP convex_intersect(VP a, VP b){
    VP plist;
    int n=a.size(), m=b.size();
    for(int r=0; r<2; r++){
        for(int i=0; i<n; i++){
            if(in_poly(a[i], b) >= 0){
                plist.push_back(a[i]);
            }
        }
        swap(n, m);
        swap(a, b);
    }
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            L la(a[i], a[(i+1)%n]), lb(b[j], b[(j+1)%m]);
            if(!isParallel(la, lb) && intersectSS(la, lb)){
                plist.push_back(crosspointLL(la, lb));
            }
        }
    }
    return convex(plist);
}

vector<VP> triangulate(VP poly){
    vector<VP> ret;
    int i=0;
    while((int)poly.size() >= 3){
        int n = poly.size();
        i = (i+1)%n;
        VP tri{poly[(i-1+n)%n], poly[i], poly[(i+1)%n]};
        if(ccw(tri[0], tri[1], tri[2]) != 1) continue;
        bool isear = true;
        for(int j=0; j<n; j++){
            if(j==(i-1+n)%n || j==i || j==(i+1)%n) continue;
            if(in_poly(poly[j], tri) >= 0){
                isear = false;
                break;
            }
        }
        if(isear){
            ret.push_back(tri);
            poly.erase(poly.begin() +i);
        }
    }
    return ret;
}

int main(){
    int n;
    cin >> n;
    VP p(n);
    for(int i=0; i<n; i++){
        int x,y;
        cin >> x >> y;
        p[i] = P(x, y);
    }
    double area = getarea(p);
    vector<VP> slit;
    for(int i=-1000; i<1000; i++){
        VP sq(4);
        for(int d=0; d<4; d++){
            double x = (d==0 or d==3)? i: i+0.5;
            double y = (d<2)? -1000: 1000;
            sq[d] = P(x, y);
        }
        slit.push_back(sq);
    }
    double s = 0;
    vector<VP> tris = triangulate(p);
    for(VP &tri: tris){
        for(VP &sq: slit){
            s += getarea(convex_intersect(tri, sq));
        }
    }
    cout << fixed << setprecision(10);
    cout << max(s, area-s) << endl;
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3512
final_rank: 7

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

#define EQ(a,b) (abs((a)-(b)) < EPS)
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define fs first
#define sc second
#define pb push_back
#define sz size()
#define all(a) (a).begin(),(a).end()

using namespace std;
typedef long double D;
typedef complex<D> P;
typedef pair<P,P> L;
typedef vector<P> Poly;
typedef pair<P,D> C;

const D EPS = 1e-8;
const D PI = acos(-1);

const int MAX_X = 1000, MAX_Y = 1000;

//for vector
inline P unit(P p){return p/abs(p);}

inline pair<P,P> norm(P p){return make_pair(p*P(0,1),p*P(0,-1));}

inline D dot(P x, P y){return real(conj(x)*y);}

inline D cross(P x, P y){return imag(conj(x)*y);}

inline bool para(L a,L b){return abs(cross(a.fs-a.sc,b.fs-b.sc))<EPS;}

inline int ccw(P a,P b,P c){
  b -= a;c -= a;
  if (cross(b,c)>EPS) return 1;   //counter clockwise
  if (cross(b,c)<-EPS) return -1; //clockwise
  if (dot(b, c)<-EPS) return 2;   //c--a--b on line
  if (abs(b)+EPS<abs(c)) return -2;   //a--b--c on line
  return 0;                       //on segment
}

inline bool is_cp(L a,L b){
  if(ccw(a.fs,a.sc,b.fs)*ccw(a.fs,a.sc,b.sc)<=0)
    if(ccw(b.fs,b.sc,a.fs)*ccw(b.fs,b.sc,a.sc)<=0)return true;
  return false;
}

inline P line_cp(L a,L b){
  return a.fs+(a.sc-a.fs)*cross(b.sc-b.fs,b.fs-a.fs)/cross(b.sc-b.fs,a.sc-a.fs);
}

inline D area(Poly p){
  if(p.sz<3)return 0;
  D res = cross(p[p.sz-1],p[0]);
  rep(i,p.sz-1)res += cross(p[i],p[i+1]);
  return res/2;
}

int main(){
  int n;
  cin >> n;

  Poly p(n);
  rep(i,n){
    int x,y;
    cin >> x >> y; x*=2; y*=2;
    p[i] = P(x,y);
  }

  D S = area(p);

  vector< vector<D> > v(4*MAX_X+1);
  for(int i=-2*MAX_X;i<=2*MAX_X;i++){
    L l = L( P(i,-2*MAX_Y-1), P(i,2*MAX_Y+1) );
    for(int j=0;j<n;j++){
      L seg = L( p[j], p[(j+1)%n] );
      if(!para(seg,l) && is_cp(seg,l)){
	P cp = line_cp(seg,l);
	if( abs(cp - (seg.fs.real()<seg.sc.real()?seg.sc:seg.fs)) > EPS){
	  v[i+2*MAX_X].push_back(cp.imag());
	}
      }
    }
    sort(v[i+2*MAX_X].begin(), v[i+2*MAX_X].end());
  }

  D sum = 0;
  for(int i=0;i<2*MAX_X;i++){
    assert(v[2*i].size()%2 == 0 && v[2*i+1].size()%2 == 0);
    assert(v[2*i].size() == v[2*i+1].size());

    for(int j=0;j<v[2*i].size();j+=2){
      sum += (abs(v[2*i][j]-v[2*i][j+1])+abs(v[2*i+1][j]-v[2*i+1][j+1]))/2;
    }
  }

  cout << fixed << setprecision(9) << max(sum,S-sum)/4 << endl;
}
accuracy: 1
time_ms: 100
memory_kb: 9444
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)n; ++i)
#define sz(s) ((int)(s.size()))

typedef complex<double> P;

typedef vector<P> poly;

typedef pair<P, P> L;

const double EPS = 1e-9;

double cross(const P &a, const P &b) { return imag(conj(a) * b); }
double dot(const P &a, const P &b) { return real(conj(a) * b); }

int ccw(P a, P b, P c) {
	double d = cross(b -= a, c -= a);
	return d > EPS ? 1 : d<-EPS ? -1 : dot(b, c) < -EPS ? 2 : norm(b) + EPS < norm(c) ? -2 : 0;
}

#define DI(l) ((l).second - (l).first)
#define CCW(l, a) ccw((l).first, (l).second, (a))

bool intersectSS(const L &s, const L &t) { return CCW(s, t.first)*CCW(s, t.second)<=0 && CCW(t, s.first)*CCW(t, s.second) <= 0; }
P crosspoint(const L &l, const L &m) {
	P a = DI(l), b = DI(m);
	double A  = cross(a, b), B = cross(a, l.second - m.first);
	return m.first + B / A * b;
}

double signed_area(const poly &v) {
	double res = 0;
	rep(i, sz(v)) res += cross(v[i], v[(i+1)%sz(v)]);
	return res * 0.5;
}



vector<P> v;
double calc(double x) {
	L a(P(x, -1e3), P(x, 1e3)), b(P(x+0.5, -1e3), P(x+0.5, 1e3));

	vector<double> ap, bp;
	rep(i, sz(v)) {
		L l = L(v[i], v[(i+1)%sz(v)]);
		if (!(intersectSS(l, a) && intersectSS(l, b))) continue;
		ap.push_back(imag(crosspoint(l, a)));
		bp.push_back(imag(crosspoint(l, b)));
	}
	sort(ap.begin(), ap.end());
	sort(bp.begin(), bp.end());
	assert(sz(ap) % 2 == 0);
	double S = 0;
	rep(i, sz(ap)/2) {
		S +=  (ap[i*2 + 1] - ap[i*2] + bp[i*2 + 1] - bp[i*2]) * 0.5 * 0.5;
	}
	return S;
}
int main(int argc, char *argv[]) {
	int N;
	cin >> N;
	rep(i, N) {
		double x, y;
		cin >> x >> y;
		v.push_back(P(x, y));
	}

	double s0 = 0, s1 = 0;
	for(double x = -1e3; x <= 1e3; x += 1) {
		s0 += calc(x);
	}
	for(double x = -1e3 - 0.5; x <= 1e3; x += 1) {
		s1 += calc(x);
	}

	printf("%.20f\n", max(s0, s1));
}
accuracy: 1
time_ms: 40
memory_kb: 1284
final_rank: 3