Problem:
Problem H
Rotating Cutter Bits
The machine tool technology never stops its development. One of the recent proposals is more flexible lathes in which not only the workpiece but also the cutter bit rotate around parallel axles in synchronization. When the lathe is switched on, the workpiece and the cutter bit start rotating at the same angular velocity, that is, to the same direction and at the same rotational speed. On collision with the cutter bit, parts of the workpiece that intersect with the cutter bit are cut out.
To show the usefulness of the mechanism, you are asked to simulate the cutting process by such a lathe.
Although the workpiece and the cutter bit may have complex shapes, focusing on cross sections of them on a plane perpendicular to the spinning axles would suffice. We introduce an $xy$-coordinate system on a plane perpendicular to the two axles, in which the center of rotation of the workpiece is at the origin $(0, 0)$, while that of the cutter bit is at $(L, 0)$. You can assume both the workpiece and the cutter bit have polygonal cross sections, not necessarily convex.
Note that, even when this cross section of the workpiece is divided into two or more parts, the workpiece remain undivided on other cross sections.
We refer to the lattice points (points with both $x$ and $y$ coordinates being integers) strictly inside, that is, inside and not on an edge, of the workpiece before the rotation as
points
of interest, or POI in short.
Our interest is in how many POI will remain after one full rotation of 360 degrees of both the workpiece and the cutter bit. POI are said to remain if they are strictly inside the resultant workpiece. Write a program that counts them for the given workpiece and cutter bit configuration.
Figure H.1(a) illustrates the workpiece (in black line) and the cutter bit (in blue line) given in Sample Input 1. Two circles indicate positions of the rotation centers of the workpiece and the cutter bit. The red cross-shaped marks indicate the POI.
Figure H.1(b) illustrates the workpiece and the cutter bit in progress in case that the rotation direction is clockwise. The light blue area indicates the area cut-off.
Figure H.1(c) illustrates the result of this sample. Note that one of POI is on the edge of the resulting shape. You should not count this point. There are eight POI remained.
Figure H.1. The workpiece and the cutter bit in Sample 1
Input
The input consists of a single test case with the following format.
$M$ $N$ $L$
$x_{w1}$ $y_{w1}$
...
$x_{wM}$ $y_{wM}$
$x_{c1}$ $y_{c1}$
...
$x_{cN}$ $y_{cN}$
The first line contains three integers. $M$ is the number of vertices of the workpiece $(4 \leq M \leq 20)$
and $N$ is the number of vertices of the cutter bit $(4 \leq N \leq 20)$. $L$ specifies the position of the
rotation center of the cutter bit $(1 \leq L \leq 10000)$.
Each of the following $M$ lines contains two integers. The $i$-th line has $x_{wi}$ and $y_{wi}$, telling that the position of the $i$-th vertex of
...(truncated)

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 20005

enum Type{
	YES_L,
	YES_R,
	NO_L,
	NO_MID,
	NO_R,
};


struct Info{
	Info(int arg_left,int arg_right){
		left = arg_left;
		right = arg_right;
	}
	bool operator<(const struct Info &arg) const{ //左端の昇順

		return left < arg.left;
	}
	int left,right;
};



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{
		return x != p.x? x < p.x: 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];
};

struct Circle{
	Point center;
	double r;
};

struct Range{

	int left,right;
};


int M,N;
int ADD = 10000;
int num_line_work,num_line_cut;
double L;
double e = 0.5;
double NUM = 40000;
vector<Info> YES_TATE[SIZE],YES_YOKO[SIZE],final_TATE[SIZE];
vector<Info> NOT_TATE[SIZE],NOT_YOKO[SIZE];
vector<Info> check_TATE[SIZE],check_YOKO[SIZE];
Polygon WORK,CUT;
Line L_work[25],L_cut[25];

int boss[50],height[50];
bool deleted[100];
Range range[50];
map<int,int> MAP,REV;
Type type[100];



double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

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;

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;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

Point project(Line l,Point p){

	Vector base = l.p[1]-l.p[0];
	double r = dot(p-l.p[0],base)/norm(base);
	return l.p[0]+base*r;
}

//円と直線の交点を求める関数
vector<Point> getCrossPoints(Circle c,Line l){

	vector<Point> ret;

	Vector pr = project(l,c.center);
	Vector e = (l.p[1]-l.p[0])/abs(l.p[1]-l.p[0]);

	double base;

	if(fabs(c.r*c.r-norm(pr-c.center)) < EPS){

		base = 0;
	}else{
		base = sqrt(c.r*c.r-norm(pr-c.center));
	}

	ret.push_back(Point(pr+e*base));
	ret.push_back(Point(pr-e*base));

	return ret;
}


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]);
}

int getInt(double tmp){

	tmp = round(tmp);
	return (int)tmp;
}

bool isInt(double tmp){

	return fabs(round(tmp)-tmp) < EPS;
}

//縦線か判定
bool isVertical(Line tmp_line){

	return fabs(tmp_line.p[0].x-tmp_line.p[1].x) < EPS;
}

/*
 * 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);
}


int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}


void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	if(boss_x == boss_y)return;

	if(height[boss_x] > height[boss_y]){

		range[boss_x].left = min(range[boss_x].left,range[boss_y].left);
		range[boss_x].right = max(range[boss_x].right,range[boss_y].right);

		boss[boss_y] = boss_x;

	}else if(height[boss_x] < height[boss_y]){

		range[boss_y].left = min(range[boss_x].left,range[boss_y].left);
		range[boss_y].right = max(range[boss_x].right,range[boss_y].right);

		boss[boss_x] = boss_y;

	}else{ //height[boss_x] == height[boss_y]

		range[boss_x].left = min(range[boss_x].left,range[boss_y].left);
		range[boss_x].right = max(range[boss_x].right,range[boss_y].right);

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){
		boss[i] = i;
		height[i] = 0;
	}
}


int main(){

	scanf("%d %d %lf",&M,&N,&L);

	double x,y;
	double min_x = BIG_NUM,max_x = -BIG_NUM,min_y = BIG_NUM,max_y = -BIG_NUM;

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

		scanf("%lf %lf",&x,&y);
		WORK.push_back(Point(x,y));

		min_x = min(min_x,x);
		max_x = max(max_x,x);

		min_y = min(min_y,y);
		max_y = max(max_y,y);
	}

	num_line_work = 0;
	for(int i = 0; i < M; i++){

		L_work[num_line_work].p[0] = WORK[i];
		L_work[num_line_work].p[1] = WORK[(i+1)%M];
		num_line_work++;
	}


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

		scanf("%lf %lf",&x,&y);
		CUT.push_back(Point(x,y));
	}

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

		L_cut[num_line_cut].p[0] = CUT[i];
		L_cut[num_line_cut].p[1] = CUT[(i+1)%N];
		num_line_cut++;
	}

	//横
	for(double Y = max_y-1.0; fabs(min_y-Y) > EPS; Y -= 1.0){

		vector<Point> vec;
		Line tmp_line = Line(Point(-NUM,Y),Point(NUM,Y));

		for(int i = 0; i < num_line_work; i++){
			if(!is_Cross(tmp_line,L_work[i]))continue;

			vec.push_back(calc_Cross_Point(tmp_line,L_work[i]));
		}
		sort(vec.begin(),vec.end());
		vec.erase(unique(vec.begin(),vec.end()),vec.end());

		for(int i = 0; i < vec.size()-1; i++){
			if(getInt(vec[i].x)+1 > getInt(vec[i+1].x)-1)continue;
			if(contains(WORK,(vec[i]+vec[i+1])/2) != 2)continue;

			YES_YOKO[getInt(Y)+ADD].push_back(Info(getInt(vec[i].x)+1,getInt(vec[i+1].x)-1));
		}
	}

	//縦
	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

		vector<Point> vec;
		Line tmp_line = Line(Point(X,-NUM),Point(X,NUM));

		for(int i = 0; i < num_line_work; i++){
			if(!is_Cross(tmp_line,L_work[i]))continue;

			vec.push_back(calc_Cross_Point(tmp_line,L_work[i]));
		}
		sort(vec.begin(),vec.end());
		vec.erase(unique(vec.begin(),vec.end()),vec.end());

		for(int i = 0; i < vec.size()-1; i ++){
			if(getInt(vec[i].y)+1 > getInt(vec[i+1].y)-1)continue;
			if(contains(WORK,(vec[i]+vec[i+1])/2) != 2)continue;

			YES_TATE[getInt(X)+ADD].push_back(Info(getInt(vec[i].y)+1,getInt(vec[i+1].y)-1));
		}
	}

	Circle C1,C2;

	//切断
	for(int i = 0; i < num_line_cut; i++){
		if(isVertical(L_cut[i])){ //縦線

			C1.r = L;
			C2.r = L;

			C1.center = L_cut[i].p[0];
			C2.center = L_cut[i].p[1];

			if(C2.center.y > C1.center.y){

				swap(C1,C2); //C1の方が上
			}

			for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

				vector<Point> vec;
				Line tmp_line = Line(Point(X,-NUM),Point(X,NUM));

				if(getDistanceSP(tmp_line,C1.center) > C1.r+EPS)continue;

				vector<Point> cross_V1 = getCrossPoints(C1,tmp_line);
				if(cross_V1[1].y > cross_V1[0].y){

					swap(cross_V1[0],cross_V1[1]);
				}

				vector<Point> cross_V2 = getCrossPoints(C2,tmp_line);
				if(cross_V2[1].y > cross_V2[0].y){

					swap(cross_V2[0],cross_V2[1]);
				}

				for(int k = 0; k < 2; k++){

					double y1 = cross_V1[k].y;
					if(!isInt(y1)){
						y1 = floor(y1);
					}

					double y2 = cross_V2[k].y;
					if(!isInt(y2)){

						y2 = ceil(y2);
					}
					NOT_TATE[getInt(X)+ADD].push_back(Info(getInt(y2),getInt(y1)));
				}
			}


		}else{ //横線

			C1.r = L;
			C2.r = L;

			C1.center = L_cut[i].p[0];
			C2.center = L_cut[i].p[1];

			if(C2.center.x > C1.center.x){

				swap(C1,C2); //C1の方が右
			}

			for(double Y = max_y-1.0; fabs(min_y-Y) > EPS; Y -= 1.0){

				vector<Point> vec;
				Line tmp_line = Line(Point(-NUM,Y),Point(NUM,Y));

				if(getDistanceSP(tmp_line,C1.center) > C1.r+EPS)continue;

				vector<Point> cross_V1 = getCrossPoints(C1,tmp_line);
				if(cross_V1[1].x > cross_V1[0].x){

					swap(cross_V1[0],cross_V1[1]);
				}

				vector<Point> cross_V2 = getCrossPoints(C2,tmp_line);
				if(cross_V2[1].x > cross_V2[0].x){

					swap(cross_V2[0],cross_V2[1]);
				}

				for(int k = 0; k < 2; k++){

					double x1 = cross_V1[k].x;
					if(!isInt(x1)){
						x1 = floor(x1);
					}

					double x2 = cross_V2[k].x;
					if(!isInt(x2)){

						x2 = ceil(x2);
					}

					NOT_YOKO[getInt(Y)+ADD].push_back(Info(getInt(x2),getInt(x1)));
				}
			}
		}
	}

	//NOT区間のマージ
	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

		int int_X = getInt(X);
		init();
		int num = (int)NOT_TATE[int_X+ADD].size();

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

			range[i].left = NOT_TATE[int_X+ADD][i].left;
			range[i].right = NOT_TATE[int_X+ADD][i].right;
		}
		for(int i = 0; i < num-1; i++){
			for(int k = i+1; k < num; k++){
				if(range[i].left > range[k].right || range[i].right < range[k].left)continue;

				unite(i,k);
			}
		}

		for(int i = 0; i < num; i++){
			if(i != get_boss(i))continue;

			check_TATE[int_X+ADD].push_back(Info(range[i].left,range[i].right));
		}
		sort(check_TATE[int_X+ADD].begin(),check_TATE[int_X+ADD].end());
	}

	for(double Y = max_y-1.0; fabs(min_y-Y) > EPS; Y -= 1.0){

		int int_Y = getInt(Y);
		init();
		int num = (int)NOT_YOKO[int_Y+ADD].size();

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

			range[i].left = NOT_YOKO[int_Y+ADD][i].left;
			range[i].right = NOT_YOKO[int_Y+ADD][i].right;
		}
		for(int i = 0; i < num-1; i++){
			for(int k = i+1; k < num; k++){
				if(range[i].left > range[k].right || range[i].right < range[k].left)continue;

				unite(i,k);
			}
		}

		for(int i = 0; i < num; i++){
			if(i != get_boss(i))continue;

			check_YOKO[int_Y+ADD].push_back(Info(range[i].left,range[i].right));
		}
		sort(check_YOKO[int_Y+ADD].begin(),check_YOKO[int_Y+ADD].end());
	}

	//最終的に生きている縦の区間を求める
	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){


		vector<int> V;
		MAP.clear();
		REV.clear();

		int int_X = getInt(X);

		if(YES_TATE[int_X+ADD].size() == 0)continue;

		//生きてる区間から消え区間を除く
		for(int i = 0; i < YES_TATE[int_X+ADD].size(); i++){
			int L = YES_TATE[int_X+ADD][i].left;

			for(int k = 0; k < check_TATE[int_X+ADD].size(); k++){
				if(check_TATE[int_X+ADD][k].right < L)continue;

				if(check_TATE[int_X+ADD][k].left <= L){

					if(check_TATE[int_X+ADD][k].right >= YES_TATE[int_X+ADD][i].right){
						L = BIG_NUM;
						break;
					}else{

						L = check_TATE[int_X+ADD][k].right+1;
					}

				}else{ //check_TATE[int_X+ADD][k].left > L

					if(check_TATE[int_X+ADD][k].left > YES_TATE[int_X+ADD][i].right){

						final_TATE[int_X+ADD].push_back(Info(L,YES_TATE[int_X+ADD][i].right));
						L = BIG_NUM;
						break;
					}else{

						final_TATE[int_X+ADD].push_back(Info(L,check_TATE[int_X+ADD][k].left-1));
						if(check_TATE[int_X+ADD][k].right >= YES_TATE[int_X+ADD][i].right){
							L = BIG_NUM;
							break;
						}else{

							L = check_TATE[int_X+ADD][k].right+1;
						}
					}
				}
			}
			if(L <= YES_TATE[int_X+ADD][i].right){

				final_TATE[int_X+ADD].push_back(Info(L,YES_TATE[int_X+ADD][i].right));
			}
		}
	}

	int ans = 0;

	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

		int int_X = getInt(X);
		for(int i = 0; i < final_TATE[int_X+ADD].size(); i++){
			for(int Y = final_TATE[int_X+ADD][i].left; Y <= final_TATE[int_X+ADD][i].right; Y++){

				//該当するY座標においてint_Xが消え区間に入っていないか
				int left = 0,right = check_YOKO[Y+ADD].size()-1,mid = (left+right)/2;
				int loc = -1;

				//int_X以上のrightを持つ最小のインデックスを求める
				while(left <= right){
					if(check_YOKO[Y+ADD][mid].right >= int_X){

						loc = mid;
						right = mid-1;
					}else{

						left = mid+1;
					}
					mid = (left+right)/2;
				}
				if(loc == -1){
					ans++;
					continue;
				}
				if(check_YOKO[Y+ADD][loc].left <= int_X)continue;

				ans++;
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 1410
memory_kb: 12192
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 20005

enum Type{
	YES_L,
	YES_R,
	NO_L,
	NO_MID,
	NO_R,
};


struct Info{
	Info(int arg_left,int arg_right){
		left = arg_left;
		right = arg_right;
	}
	bool operator<(const struct Info &arg) const{ //左端の昇順

		return left < arg.left;
	}
	int left,right;
};



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{
		return x != p.x? x < p.x: 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];
};

struct Circle{
	Point center;
	double r;
};

struct Range{

	int left,right;
};


int M,N;
int ADD = 10000;
int num_line_work,num_line_cut;
double L;
double e = 0.5;
double NUM = 40000;
vector<Info> YES_TATE[SIZE],YES_YOKO[SIZE],final_TATE[SIZE];
vector<Info> NOT_TATE[SIZE],NOT_YOKO[SIZE];
vector<Info> check_TATE[SIZE],check_YOKO[SIZE];
Polygon WORK,CUT;
Line L_work[25],L_cut[25];

int boss[50],height[50];
bool deleted[100];
Range range[50];
map<int,int> MAP,REV;
Type type[100];



double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

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;

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;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

Point project(Line l,Point p){

	Vector base = l.p[1]-l.p[0];
	double r = dot(p-l.p[0],base)/norm(base);
	return l.p[0]+base*r;
}

//円と直線の交点を求める関数
vector<Point> getCrossPoints(Circle c,Line l){

	vector<Point> ret;

	Vector pr = project(l,c.center);
	Vector e = (l.p[1]-l.p[0])/abs(l.p[1]-l.p[0]);

	double base;

	if(fabs(c.r*c.r-norm(pr-c.center)) < EPS){

		base = 0;
	}else{
		base = sqrt(c.r*c.r-norm(pr-c.center));
	}

	ret.push_back(Point(pr+e*base));
	ret.push_back(Point(pr-e*base));

	return ret;
}


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]);
}

int getInt(double tmp){

	tmp = round(tmp);
	return (int)tmp;
}

bool isInt(double tmp){

	return fabs(round(tmp)-tmp) < EPS;
}

//縦線か判定
bool isVertical(Line tmp_line){

	return fabs(tmp_line.p[0].x-tmp_line.p[1].x) < EPS;
}

/*
 * 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);
}

double getTop(Line tmp_line){

	return max(tmp_line.p[0].y,tmp_line.p[1].y);
}
double getUnder(Line tmp_line){

	return min(tmp_line.p[0].y,tmp_line.p[1].y);
}
double getL(Line tmp_line){

	return min(tmp_line.p[0].x,tmp_line.p[1].x);
}
double getR(Line tmp_line){

	return max(tmp_line.p[0].x,tmp_line.p[1].x);
}

//自分のボスのindexを取得しつつ、経路圧縮を行う関数
int get_boss(int id){
	if(boss[id] == id)return id; //自分が代表なら、自分の値を返す
	else{
		return boss[id] = get_boss(boss[id]); //代表でないなら、自分が所属する組織の代表を返しつつ、経路圧縮
	}
}


void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[boss_x] > height[boss_y]){

		range[boss_x].left = min(range[boss_x].left,range[boss_y].left);
		range[boss_x].right = max(range[boss_x].right,range[boss_y].right);

		boss[boss_y] = boss_x;

	}else if(height[boss_x] < height[boss_y]){

		range[boss_y].left = min(range[boss_x].left,range[boss_y].left);
		range[boss_y].right = max(range[boss_x].right,range[boss_y].right);

		boss[boss_x] = boss_y;

	}else{ //height[boss_x] == height[boss_y]

		range[boss_x].left = min(range[boss_x].left,range[boss_y].left);
		range[boss_x].right = max(range[boss_x].right,range[boss_y].right);

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){
		boss[i] = i;
		height[i] = 0;
	}
}


int main(){

	scanf("%d %d %lf",&M,&N,&L);

	double x,y;
	double min_x = BIG_NUM,max_x = -BIG_NUM,min_y = BIG_NUM,max_y = -BIG_NUM;

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

		scanf("%lf %lf",&x,&y);
		WORK.push_back(Point(x,y));

		min_x = min(min_x,x);
		max_x = max(max_x,x);

		min_y = min(min_y,y);
		max_y = max(max_y,y);
	}

	num_line_work = 0;
	for(int i = 0; i < M; i++){

		L_work[num_line_work].p[0] = WORK[i];
		L_work[num_line_work].p[1] = WORK[(i+1)%M];
		num_line_work++;
	}


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

		scanf("%lf %lf",&x,&y);
		CUT.push_back(Point(x,y));
	}

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

		L_cut[num_line_cut].p[0] = CUT[i];
		L_cut[num_line_cut].p[1] = CUT[(i+1)%N];
		num_line_cut++;
	}

	//横
	for(double Y = max_y-1.0; fabs(min_y-Y) > EPS; Y -= 1.0){

		//printf("\nY:%.0lf\n",Y);

		vector<Point> vec;
		Line tmp_line = Line(Point(-NUM,Y),Point(NUM,Y));

		for(int i = 0; i < num_line_work; i++){
			if(!is_Cross(tmp_line,L_work[i]))continue;

			vec.push_back(calc_Cross_Point(tmp_line,L_work[i]));
		}
		sort(vec.begin(),vec.end());
		vec.erase(unique(vec.begin(),vec.end()),vec.end());

		for(int i = 0; i < vec.size()-1; i++){
			if(getInt(vec[i].x)+1 > getInt(vec[i+1].x)-1)continue;
			if(contains(WORK,(vec[i]+vec[i+1])/2) != 2)continue;

			//printf("%d x:%.0lf-%.0lf\n",i,vec[i].x,vec[i+1].x);

			YES_YOKO[getInt(Y)+ADD].push_back(Info(getInt(vec[i].x)+1,getInt(vec[i+1].x)-1));
		}
		/*for(int i = 0; i < YES_YOKO[getInt(Y)+ADD].size(); i++){

			printf("L:%d R:%d\n",YES_YOKO[getInt(Y)+ADD][i].left,YES_YOKO[getInt(Y)+ADD][i].right);
		}*/

	}

	//printf("\n");

	//縦
	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

		//printf("\nX:%.0lf\n",X);
		vector<Point> vec;
		Line tmp_line = Line(Point(X,-NUM),Point(X,NUM));

		for(int i = 0; i < num_line_work; i++){
			if(!is_Cross(tmp_line,L_work[i]))continue;

			vec.push_back(calc_Cross_Point(tmp_line,L_work[i]));
		}
		sort(vec.begin(),vec.end());
		vec.erase(unique(vec.begin(),vec.end()),vec.end());

		for(int i = 0; i < vec.size()-1; i ++){
			if(getInt(vec[i].y)+1 > getInt(vec[i+1].y)-1)continue;
			if(contains(WORK,(vec[i]+vec[i+1])/2) != 2)continue;

			YES_TATE[getInt(X)+ADD].push_back(Info(getInt(vec[i].y)+1,getInt(vec[i+1].y)-1));
		}

		/*for(int i = 0; i < YES_TATE[getInt(X)+ADD].size(); i++){

			printf("L:%d R:%d\n",YES_TATE[getInt(X)+ADD][i].left,YES_TATE[getInt(X)+ADD][i].right);
		}*/
	}

	Circle C1,C2;

	//printf("\n\n★★切断\n");

	//切断
	for(int i = 0; i < num_line_cut; i++){
		if(isVertical(L_cut[i])){ //縦線

			C1.r = L;
			C2.r = L;

			C1.center = L_cut[i].p[0];
			C2.center = L_cut[i].p[1];

			if(C2.center.y > C1.center.y){

				swap(C1,C2); //C1の方が上
			}

			for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

				vector<Point> vec;
				Line tmp_line = Line(Point(X,-NUM),Point(X,NUM));

				if(getDistanceSP(tmp_line,C1.center) > C1.r+EPS)continue;

				vector<Point> cross_V1 = getCrossPoints(C1,tmp_line);
				if(cross_V1[1].y > cross_V1[0].y){

					swap(cross_V1[0],cross_V1[1]);
				}

				vector<Point> cross_V2 = getCrossPoints(C2,tmp_line);
				if(cross_V2[1].y > cross_V2[0].y){

					swap(cross_V2[0],cross_V2[1]);
				}

				//printf("X:%.0lf\n",X);

				for(int k = 0; k < 2; k++){

					double y1 = cross_V1[k].y;
					//printf("最初y1:%.5lf\n",y1);
					if(!isInt(y1)){
						y1 = floor(y1);
					}
					//printf("結果y1:%.5lf\n",y1);

					double y2 = cross_V2[k].y;
					//printf("最初y2:%.5lf\n",y2);
					if(!isInt(y2)){

						y2 = ceil(y2);
					}
					//printf("結果y2:%.5lf\n",y2);
					NOT_TATE[getInt(X)+ADD].push_back(Info(getInt(y2),getInt(y1)));
				}
			}


		}else{ //横線

			C1.r = L;
			C2.r = L;

			C1.center = L_cut[i].p[0];
			C2.center = L_cut[i].p[1];

			if(C2.center.x > C1.center.x){

				swap(C1,C2); //C1の方が右
			}

			for(double Y = max_y-1.0; fabs(min_y-Y) > EPS; Y -= 1.0){

				vector<Point> vec;
				Line tmp_line = Line(Point(-NUM,Y),Point(NUM,Y));

				if(getDistanceSP(tmp_line,C1.center) > C1.r+EPS)continue;

				vector<Point> cross_V1 = getCrossPoints(C1,tmp_line);
				if(cross_V1[1].x > cross_V1[0].x){

					swap(cross_V1[0],cross_V1[1]);
				}

				vector<Point> cross_V2 = getCrossPoints(C2,tmp_line);
				if(cross_V2[1].x > cross_V2[0].x){

					swap(cross_V2[0],cross_V2[1]);
				}

				//printf("\nY:%.0lf\n",Y);

				for(int k = 0; k < 2; k++){

					double x1 = cross_V1[k].x;
					//printf("x1:%.5lf\n",x1);
					if(!isInt(x1)){
						x1 = floor(x1);
					}
					//printf("\n結果 x1:%.5lf\n",x1);

					double x2 = cross_V2[k].x;
					//printf("x2:%.5lf\n",x2);
					if(!isInt(x2)){

						x2 = ceil(x2);
					}
					//printf("結果 x2:%.5lf\n",x2);

					NOT_YOKO[getInt(Y)+ADD].push_back(Info(getInt(x2),getInt(x1)));
				}
			}
		}
	}

	//NOT区間のマージ
	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

		int int_X = getInt(X);
		init();
		int num = (int)NOT_TATE[int_X+ADD].size();

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

			range[i].left = NOT_TATE[int_X+ADD][i].left;
			range[i].right = NOT_TATE[int_X+ADD][i].right;
		}
		for(int i = 0; i < num-1; i++){
			for(int k = i+1; k < num; k++){
				if(range[i].left > range[k].right || range[i].right < range[k].left)continue;

				unite(i,k);
			}
		}

		for(int i = 0; i < num; i++){
			if(i != get_boss(i))continue;

			check_TATE[int_X+ADD].push_back(Info(range[i].left,range[i].right));
		}
		sort(check_TATE[int_X+ADD].begin(),check_TATE[int_X+ADD].end());

		/*printf("\nX:%.0lf\n",X);
		for(int i = 0; i < check_TATE[int_X+ADD].size(); i++){

			printf("L:%d R:%d\n",check_TATE[int_X+ADD][i].left,check_TATE[int_X+ADD][i].right);
		}*/
	}

	/*printf("\n");
	printf("★★RANGE★★\n");*/

	for(double Y = max_y-1.0; fabs(min_y-Y) > EPS; Y -= 1.0){

		int int_Y = getInt(Y);
		init();
		int num = (int)NOT_YOKO[int_Y+ADD].size();

		//printf("\nY:%.0lf\n",Y);

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

			range[i].left = NOT_YOKO[int_Y+ADD][i].left;
			range[i].right = NOT_YOKO[int_Y+ADD][i].right;
			//printf("i:%d L:%d R:%d\n",i,range[i].left,range[i].right);
		}
		for(int i = 0; i < num-1; i++){
			for(int k = i+1; k < num; k++){
				if(range[i].left > range[k].right || range[i].right < range[k].left)continue;

				unite(i,k);
			}
		}

		for(int i = 0; i < num; i++){
			if(i != get_boss(i))continue;

			check_YOKO[int_Y+ADD].push_back(Info(range[i].left,range[i].right));
		}
		sort(check_YOKO[int_Y+ADD].begin(),check_YOKO[int_Y+ADD].end());

		/*printf("\nY:%.0lf\n",Y);
		for(int i = 0; i < check_YOKO[int_Y+ADD].size(); i++){

			printf("L:%d R:%d\n",check_YOKO[int_Y+ADD][i].left,check_YOKO[int_Y+ADD][i].right);
		}*/
	}

	//最終的に生きている縦の区間を求める
	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){


		vector<int> V;
		MAP.clear();
		REV.clear();

		int int_X = getInt(X);
		//printf("\nint_X:%d\n",int_X);

		if(YES_TATE[int_X+ADD].size() == 0)continue;


		for(int i = 0; i < YES_TATE[int_X+ADD].size(); i++){
			int L = YES_TATE[int_X+ADD][i].left;

			for(int k = 0; k < check_TATE[int_X+ADD].size(); k++){
				if(check_TATE[int_X+ADD][k].right < L)continue;

				//printf("L:%d\n",L);

				if(check_TATE[int_X+ADD][k].left <= L){

					if(check_TATE[int_X+ADD][k].right >= YES_TATE[int_X+ADD][i].right){
						L = BIG_NUM;
						break;
					}else{

						L = check_TATE[int_X+ADD][k].right+1;
					}

				}else{ //check_TATE[int_X+ADD][k].left > L

					if(check_TATE[int_X+ADD][k].left > YES_TATE[int_X+ADD][i].right){

						final_TATE[int_X+ADD].push_back(Info(L,YES_TATE[int_X+ADD][i].right));
						L = BIG_NUM;
						break;
					}else{

						final_TATE[int_X+ADD].push_back(Info(L,check_TATE[int_X+ADD][k].left-1));
						if(check_TATE[int_X+ADD][k].right >= YES_TATE[int_X+ADD][i].right){
							L = BIG_NUM;
							break;
						}else{

							L = check_TATE[int_X+ADD][k].right+1;
						}
					}
				}
			}
			if(L <= YES_TATE[int_X+ADD][i].right){

				final_TATE[int_X+ADD].push_back(Info(L,YES_TATE[int_X+ADD][i].right));
			}
		}


		/*printf("final\n");
		for(int i = 0; i < final_TATE[int_X+ADD].size(); i++){

			printf("L:%d R:%d\n",final_TATE[int_X+ADD][i].left,final_TATE[int_X+ADD][i].right);
		}*/
	}

	int ans = 0;
	//int num_not = 0;

	for(double X = min_x+1.0; fabs(max_x-X) > EPS; X += 1.0){

		int int_X = getInt(X);
		for(int i = 0; i < final_TATE[int_X+ADD].size(); i++){
			for(int Y = final_TATE[int_X+ADD][i].left; Y <= final_TATE[int_X+ADD][i].right; Y++){

				//該当するY座標においてint_Xが死に区間に入っていないか
				int left = 0,right = check_YOKO[Y+ADD].size()-1,mid = (left+right)/2;
				int loc = -1;

				//int_X以上のrightを持つ最小のインデックスを求める
				while(left <= right){
					if(check_YOKO[Y+ADD][mid].right >= int_X){

						loc = mid;
						right = mid-1;
					}else{

						left = mid+1;
					}
					mid = (left+right)/2;
				}
				if(loc == -1){

					//printf("(%d,%d)がOK\n",int_X,Y);
					ans++;
					continue;
				}
				if(check_YOKO[Y+ADD][loc].left <= int_X){
					//num_not++;
					continue;
				}

				//printf("(%d,%d)がOK\n",int_X,Y);
				ans++;
			}
		}
	}

	//printf("num_not:%d\n",num_not);
	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 1350
memory_kb: 12344
final_rank: 4

code_snippet: #include <iostream>
#include <complex>
#include <vector>
#include <algorithm>
#include <utility>
#include <cmath>
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;

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
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(abs(cross(a,b))<EPS && dot(a,b)<EPS) return 0;
        if(a.Y<=0 && b.Y>0 && cross(a,b)<0) ret = -ret;
    }
    return ret;
}

int solve(const VP &plane, const VP &cutter, double L){
    int m = plane.size();
    int n = cutter.size();
    
    //すべての格子線(タテ)について
    long long int ret = 0;
    for(int x=-10000; x<=10000; x++){
        vector<pair<double, double> > removed;
        
        //planeの外部
        vector<double> cp_y; //cross point y
        for(int i=0; i<m; i++){
            P curr = plane[i];
            P next = plane[(i+1)%m];
            if(EQ(curr.X, next.X)) continue;
            if(curr.X > next.X) swap(curr, next); //nextが右
            if(curr.X -EPS < x && x < next.X +EPS){
                cp_y.push_back(curr.Y);
            }
        }
        
        if(cp_y.empty()) continue;
        cp_y.push_back(-INF);
        cp_y.push_back(INF);
        sort(cp_y.begin(), cp_y.end());
        for(int i=0; i<(int)cp_y.size()-1; i++){
            if(in_poly(P(x, (cp_y[i] +cp_y[i+1])/2), plane) <= 0){
                removed.push_back(make_pair(cp_y[i], cp_y[i+1]));
            }
        }
        
        //辺でカットされる部分
        for(int i=0; i<n; i++){
            P curr = cutter[i];
            P next = cutter[(i+1)%n];
            if(EQ(curr.X, next.X)){ //縦に並ぶ
                if(curr.Y > next.Y) swap(curr, next); //nextが上
                if(x < curr.X -L -EPS || next.X +L +EPS < x) continue;
                double d = sqrt(L*L -(x-curr.X)*(x-curr.X));
                if(curr.Y +d > next.Y -d){
                    removed.push_back(make_pair(curr.Y -d, next.Y -d));
                    removed.push_back(make_pair(curr.Y +d, next.Y +d));
                }else{
                    removed.push_back(make_pair(curr.Y -d, next.Y +d));
                }
            }else{ //横に並ぶ
                if(curr.X > next.X) swap(curr, next); //nextが右
                if(x < curr.X -L -EPS || next.X +L +EPS < x) continue;
                double midx = (curr.X + next.X)/2;
                double nx = (x > midx)? 2*midx -x : x;
                double cd = sqrt(L*L -(nx -curr.X)*(nx -curr.X));
                double up = (nx < curr.X)? curr.Y +cd : curr.Y +L;
                double down = (nx < curr.X)? curr.Y -cd : curr.Y -L;
                if(nx < next.X -L){
                	removed.push_back(make_pair(down, up));
                }else{
                	double nd = sqrt(L*L -(nx -next.X)*(nx -next.X));
                	removed.push_back(make_pair(down, curr.Y -nd));
                    removed.push_back(make_pair(curr.Y +nd, up));
                }
            }
        }
        
        //残った格子点を加える
        sort(removed.begin(), removed.end());
        double last = -INF;
        for(int i=0; i<(int)removed.size()-1; i++){
            last = max(last, removed[i].second);
            if(last +EPS > removed[i+1].first) continue;
            double upper = floor(removed[i+1].first -EPS);
            double lower = ceil(last +EPS);
            ret += (int)(upper -lower +1 +0.5);
        }
    }
    return ret;
}

int main(){
    //input
    int m,n,L;
    cin >> m >> n >> L;
    
    VP plane(m), cutter(n);
    double x,y;
    for(int i=0; i<m; i++){
        cin >> x >> y;
        plane[i] = P(x, y);
    }
    for(int i=0; i<n; i++){
        cin >> x >> y;
        cutter[i] = P(x, y);
    }
    
    cout << solve(plane, cutter, L) << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3376
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define inf 10010
#define linf 1e16
#define eps (1e-8)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  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 k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool intersect(Line L,Segment s){
  return cross(L.p2-L.p1,s.p1-L.p1)*cross(L.p2-L.p1,s.p2-L.p1)<eps;
}

double getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

bool iscrossLC(Line l,Circle c){
  if((getDistanceLP(l,c.c)-c.r)<eps)return true;
  return false;
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector 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;
  }
  if(x)return 2;
  return 0;
}

vector<pdd> cut(double a,double b,double c,double d){
  vector<pdd> res;
  if(d-a<eps || b-c<eps)res.pb(mp(a,b));
  else if(c-a<eps && b-d<eps)res.pb(mp(linf,linf));
  else if(c-a<eps && d-b<eps)res.pb(mp(d,b));
  else if(a-c<eps && b-d<eps)res.pb(mp(a,c));
  else {
    res.pb(mp(a,c));
    res.pb(mp(d,b));
  }
  return res;
}

int n,m,R;
Polygon a,b;

ll count(Segment s){
  ll res=0;
  queue<pdd> q;
  q.push(mp(s.p1.y,s.p2.y));
  FOR(i,0,m){
    Point p1=b[i],p2=b[(i+1)%m];
    vector<pdd> v;
    vector<Point> vp,tmp;
    double h=abs(p1.y-p2.y);
    double w=abs(p1.x-p2.x);
    double u=-linf,d=linf;
    if(equals(w,0.0)){
      if(iscrossLC(s,Circle(p1,R))){
        u=max(u,p1.y+sqrt(R*R-(p1.x-s.p1.x)*(p1.x-s.p1.x)));
        d=min(d,p1.y-sqrt(R*R-(p1.x-s.p1.x)*(p1.x-s.p1.x)));
      }
      if(iscrossLC(s,Circle(p2,R))){
        u=max(u,p2.y+sqrt(R*R-(p2.x-s.p1.x)*(p2.x-s.p1.x)));
        d=min(d,p2.y-sqrt(R*R-(p2.x-s.p1.x)*(p2.x-s.p1.x)));
      }
      if(equals(u,-linf))continue;
      v.pb(mp(d,d+h));
      v.pb(mp(u-h,u));
    }
    else {
      if(iscrossLC(s,Circle(p1,R)))
        u=sqrt(R*R-(p1.x-s.p1.x)*(p1.x-s.p1.x));
      if(iscrossLC(s,Circle(p2,R)))
        d=sqrt(R*R-(p2.x-s.p1.x)*(p2.x-s.p1.x));
      if(intersect(s,Segment(p1,p2))){
        if(!equals(u,-linf) && !equals(d,linf)){
          v.pb(mp(p1.y+min(u,d),p1.y+R));
          v.pb(mp(p1.y-R,p1.y-min(u,d)));
        }
        else v.pb(mp(p1.y-R,p1.y+R));
      }
      else {
        if(!equals(u,-linf) && !equals(d,linf)){
          v.pb(mp(p1.y+min(u,d),p1.y+max(u,d)));
          v.pb(mp(p1.y-max(u,d),p1.y-min(u,d)));
        }
        else if(!equals(u,-linf))v.pb(mp(p1.y-u,p1.y+u));
        else if(!equals(d,linf))v.pb(mp(p1.y-d,p1.y+d));
      }
    }
    FOR(j,0,v.size()){
      queue<pdd> nq;
      while(q.size()){
        pdd u=q.front();
        q.pop();
        vector<pdd> vpdd=cut(u.f,u.s,v[j].f,v[j].s);
        FOR(k,0,vpdd.size()){
          if(vpdd[k].s-vpdd[k].f<eps)continue;
          if(vpdd[k].f==linf)continue;
          nq.push(vpdd[k]);
        }
      }
      while(nq.size()){
        q.push(nq.front());
        nq.pop();
      }
    }
  }
  while(q.size()){
    pdd u=q.front();
    if(u.s>eps)res+=int(u.s-eps);
    else res+=int(u.s-1);
    if(u.f>-eps)res-=int(u.f+1);
    else res-=int(u.f+eps);
    res++;
    q.pop();
  }
  return res;
}

ll count(int X){
  Line L(Point(X,0),Point(X,100));
  vector<double> v;
  FOR(i,0,n){
    Segment s(a[i],a[(i+1)%n]);
    if(isParallel(L,s))continue;
    if(!intersect(L,s))continue;
    Point M=getCrossPointLL(L,s);
    v.pb(M.y);
  }
  sort(all(v));
  ll res=0;
  FOR(i,1,v.size()){
    Point p1(X,v[i-1]),p2(X,v[i]);
    if(contains(a,p1+(p2-p1)/2.0)==2)res+=count(Segment(p1,p2));
  }
  return res;
}

ll solve(){
  ll res = 0;
  FOR(i,-inf,inf)res+=count(i);
  return res;
}

int main()
{
  cin>>n>>m>>R;
  a.resize(n);
  b.resize(m);
  FOR(i,0,n)cin>>a[i].x>>a[i].y;
  FOR(i,0,m)cin>>b[i].x>>b[i].y;
  cout<<solve()<<endl;
  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3268
final_rank: 3

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double EPS=1e-10;
const double INF=1e+10;
const double PI=acos(-1);
int sig(double r){return (r<-EPS)?-1:(r>+EPS)?+1:0;}
double ABS(double a){return max(a,-a);}
struct Pt{
	double x,y;
	Pt(){}
	Pt(double x,double y):x(x),y(y){}
	Pt operator+(const Pt &a)const{return Pt(x+a.x,y+a.y);}
	Pt operator-(const Pt &a)const{return Pt(x-a.x,y-a.y);}
	Pt operator*(const Pt &a)const{return Pt(x*a.x-y*a.y,x*a.y+y*a.x);}
	Pt operator-()const{return Pt(-x,-y);}
	Pt operator*(const double &k)const{return Pt(x*k,y*k);}
	Pt operator/(const double &k)const{return Pt(x/k,y/k);}
	double ABS()const{return sqrt(x*x+y*y);}
	double abs2()const{return x*x+y*y;}
	double arg()const{return atan2(y,x);}
	double dot(const Pt &a)const{return x*a.x+y*a.y;}
	double det(const Pt &a)const{return x*a.y-y*a.x;}
};
double tri(const Pt &a,const Pt &b,const Pt &c){return (b-a).det(c-a);}
int iSP(Pt a,Pt b,Pt c){
	int s=sig((b-a).det(c-a));
	if(s)return s;
	if(sig((b-a).dot(c-a))<0)return -2;
	if(sig((a-b).dot(c-b))<0)return +2;
	return 0;
}

int iLL(Pt a,Pt b,Pt c,Pt d){
	if(sig((b-a).det(d-c)))return 1;
	if(sig((b-a).det(c-a)))return 0;
	return -1;
}
int iSS(Pt a,Pt b,Pt c,Pt d){
	return (iSP(a,b,c)*iSP(a,b,d)<=0&&iSP(c,d,a)*iSP(c,d,b)<=0);
}
double dLP(Pt a,Pt b,Pt c){
	return ABS(tri(a,b,c))/(b-a).ABS();
}
double dSP(Pt a,Pt b,Pt c){
	if(sig((b-a).dot(c-a))<=0)return (c-a).ABS();
	if(sig((a-b).dot(c-b))<=0)return (c-b).ABS();
	return ABS(tri(a,b,c))/(b-a).ABS();
}
bool iCS(Pt a,double r,Pt b,Pt c){
	return (sig(r-dSP(b,c,a))>=0&&sig(r-max((b-a).ABS(),(c-a).ABS()))<=0);
}
pair<Pt,Pt>pCL(Pt a,double r,Pt b,Pt c){
	Pt h=b+(c-b)*(c-b).dot(a-b)/(c-b).abs2();
	double d=(h-a).ABS();
	double y=sqrt(max(r*r-d*d,0.0));
	Pt e=(c-b)/(c-b).ABS();
	return make_pair(h-e*y,h+e*y);
}
pair<Pt,Pt>pCC(Pt a,double r,Pt b,double s){
	double d=(b-a).ABS();
	double x=(d*d+r*r-s*s)/(d*2);
	Pt e=(b-a)/d,w=e*Pt(0,1)*sqrt(max(r*r-x*x,0.0));
	return make_pair(a+e*x-w,a+e*x+w);
}
int sGP(int n,Pt p[],Pt a){
	int side=-1,i;
	p[n]=p[0];
	for(i=0;i<n;i++){
		Pt p0=p[i]-a,p1=p[i+1]-a;
		if(sig(p0.det(p1))==0&&sig(p0.dot(p1))<=0)return 0;
		if(p0.y>p1.y)swap(p0,p1);
		if(sig(p0.y)<=0&&0<sig(p1.y)&&sig(p0.det(p1))>0)side=-side;
	}
	return side;
}
int X1[30];
int Y1[30];
int X2[30];
int Y2[30];
Pt p1[30];
Pt p2[30];
Pt ce[30];
int ev[11000];
double dt[11000];
inline int rdown(double a){
	if(a>=0)return (int)a;
	double b=-a;
	return -((int)b+1);
}
int main(){
	int a,b,c;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=0;i<a;i++){
		scanf("%d%d",X1+i,Y1+i);
		p1[i]=Pt((double)X1[i],(double)Y1[i]);
		X1[a]=X1[0];Y1[a]=Y1[0];
	}
	for(int i=0;i<b;i++){
		scanf("%d%d",X2+i,Y2+i);
		X2[i]+=c;
		p2[i]=Pt((double)X2[i],(double)Y2[i]);
		ce[i]=p2[i];
		ce[i].x-=(double)c;
		X2[b]=X2[0];Y2[b]=Y2[0];
	}
	ce[b]=ce[0];
	double r=(double)c;
	int ret=0;
	for(int i=-10000;i<=10000;i++){
		int sz=0;
		for(int j=0;j<a;j++){
			if(Y1[j]!=Y1[j+1]&&min(Y1[j],Y1[j+1])<=i&&i<=max(Y1[j],Y1[j+1])){
				ev[sz++]=X1[j];
			}
		}
		std::sort(ev,ev+sz);
	//	if(sz)printf("%d: \n",i);
		for(int j=0;j<sz-1;j++){
		//	printf("%d %d\n",ev[j],ev[j+1]);
		//	bool dame=false;
		//	for(int k=0;k<a;k++)if(i==Y1[k]&&i==Y1[k+1]&&min(X1[k],X1[k+1])==ev[j]&&ev[j+1]==max(X1[k],X1[k+1]))dame=true;
		//	if(dame)continue;
			if(sGP(a,p1,Pt((double)(ev[j]+ev[j+1])/2,(double)i))!=1)continue;
			double L=(double)ev[j]+0.2;
			double R=(double)ev[j+1]-0.2;
			double y=(double)i;
			int n=0;
			for(int k=0;k<b;k++){
				if(X2[k]==X2[k+1]){
					if(iSS(Pt(100000.0,y),Pt(-100000.0,y),Pt(ce[k].x-r,ce[k].y),Pt(ce[k].x-r,ce[k+1].y))){
						dt[n++]=ce[k].x-r;
						dt[n++]=ce[k].x+r;
					}
				}else{
					
				}
				if(iCS(ce[k],r,Pt(-100000,y),Pt(100000,y))){
					pair<Pt,Pt> u=pCL(ce[k],r,Pt(-100000,y),Pt(100000,y));
					dt[n++]=u.first.x;
					dt[n++]=u.second.x;
				}
			}
			dt[n++]=L;
			dt[n++]=R;
			std::sort(dt,dt+n);
			bool last=true;
			for(int k=0;k<n-1;k++){
				if(dt[k+1]-dt[k]<EPS/2)continue;
				if(dt[k]<L||dt[k+1]>R)continue;
				double M=(dt[k]+dt[k+1])/2;
				Pt mid=Pt(M,y);
				bool ok=false;
				for(int l=0;l<b;l++){
					bool c1=false;
					bool c2=false;
					bool c3=false;
					bool c4=false;
					bool rec=false;
					if((mid-ce[l]).ABS()<r-EPS){
						c1=true;
					}
					if((mid-ce[l]).ABS()<r+EPS){
						c3=true;
					}
					if((mid-ce[l+1]).ABS()<r-EPS){
						c2=true;
					}
					if((mid-ce[l+1]).ABS()<r+EPS){
						c4=true;
					}
					if(X2[l]==X2[l+1]){
						if(ce[l].x-r-EPS<M&&M<ce[l].x+r+EPS&&min(ce[l].y,ce[l+1].y)-EPS<y&&y<max(ce[l].y,ce[l+1].y)+EPS)rec=true;
					}else{
						if(min(ce[l].x,ce[l+1].x)-EPS<M&&M<max(ce[l].x,ce[l+1].x)+EPS&&ce[l].y-r-EPS<y&&y<ce[l].y+r+EPS)rec=true;
					}
					if((rec||c3||c4)&&!(c1&&c2)){
						ok=true;break;
					}
				}
				if(!ok){
				
					int rm=rdown(dt[k+1]-EPS);
					int lm=rdown(dt[k]+EPS);
					ret+=rm-lm;
					if(!last){
						int rd=rdown(dt[k]+0.5);
						if(ABS(dt[k]-rd)<EPS)ret++;
					}
					last=false;
				}else last=true;
			}
			
		}
		//if(-3<i&&i<10)printf("%d: %d\n",i,ret);
	}
	printf("%d\n",ret);
}
accuracy: 1
time_ms: 40
memory_kb: 1064
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
#define X real()
#define Y imag()
using namespace std;
typedef pair<int,int> Pi;
typedef double D;
typedef complex<D> P;
typedef pair<P,P> L;
typedef vector<P> Pol;
int M,N;
D A;
Pol w,c;
D inf=1e9,eps=1e-9;
vector<L> we,ce;
bool vert(L l){
	return l.fs.X==l.sc.X;
}
void cuts(vector<Pi>& segs,D x,D y){
	int l=ceil(x-eps);
	int r=floor(y+eps);
//	show(l);
//	show(r);
	vector<Pi> vc;
	for(Pi p:segs){
		if(l<=p.fs&&p.sc<=r) continue;
		else if(r<p.fs||p.sc<l) vc.pb(p);
		else if(p.fs<l&&r<p.sc) vc.pb(Pi(p.fs,l-1)),vc.pb(Pi(r+1,p.sc));
		else if(l<=p.fs) vc.pb(Pi(r+1,p.sc));
		else vc.pb(Pi(p.fs,l-1));
	}
	segs=vc;
}
int main(){
	cin>>M>>N>>A;
	rep(i,M){
		int x,y;
		cin>>x>>y;
		w.pb(P(x,y));
	}
	w.pb(w[0]);
	rep(i,N){
		int x,y;
		cin>>x>>y;
		c.pb(P(x,y));
	}
	c.pb(c[0]);
	rep(i,M){
		L l(w[i],w[i+1]);
		we.pb(l);
	}
	rep(i,M-1) rep(j,M-1) if(we[j].fs.X>we[j+1].fs.X) swap(we[j],we[j+1]);
	rep(i,N){
		L l(c[i],c[i+1]);
		if(c[i].X>c[i+1].X||c[i].Y>c[i+1].Y) swap(l.fs,l.sc);
		ce.pb(l);
	}
	long long ans=0;
	for(int y=-10000;y<=10000;y++){
		vector<Pi> segs;
		int prev=0;
		bool in=0;
		for(L e:we) if(vert(e)){
			int x=e.fs.X;
			int l=e.fs.Y,u=e.sc.Y;
			bool into=0;
			if(l>u) swap(l,u),into=1;
			if(l<=y&&y<=u){
				if(!into&&in&&prev+1<=x-1){
					segs.pb(Pi(prev+1,x-1));
				}
				in=into;
				prev=x;
			}
		}
		for(L e:we) if(!vert(e)&&e.fs.Y==y){
			D a=e.fs.X,b=e.sc.X;
			if(a>b) swap(a,b);
			cuts(segs,a,b);
		}
		if(segs.empty()) continue;
//		show(y);
//		for(Pi seg:segs) printf("(%d,%d)\n",seg.fs,seg.sc);
		for(L e:ce){
			P a=e.fs,b=e.sc;
//			show(a);
//			show(b);
			if(vert(e)){
				D x=a.X;
				D l=a.Y,u=b.Y;
				if(l<=y&&y<=u){
					D f=inf;
					rep(i,2){
						D dy=abs(y-(i==0?l:u));
						if(dy<=A){
							D dx=sqrt(A*A-dy*dy);
							chmin(f,dx);
						}
					}
					if(f==inf){
						cuts(segs,x-A,x+A);
					}else{
						cuts(segs,x-A,x-f);
						cuts(segs,x+f,x+A);
					}
				}else{
					vector<D> vc;
					rep(i,2){
						D dy=abs(y-(i==0?l:u));
						if(dy<=A){
							D dx=sqrt(A*A-dy*dy);
							vc.pb(dx);
						}
					}
					if(vc.empty()) continue;
					if(vc.size()==1){
						D dx=vc[0];
						cuts(segs,x-dx,x+dx);
					}else{
						D g=vc[0],h=vc[1];
						if(g>h) swap(g,h);
						cuts(segs,x-h,x-g);
						cuts(segs,x+g,x+h);
					}
				}
			}else{
				D cy=a.Y;
				D dy=abs(cy-y);
				if(dy>A) continue;
				D dx=sqrt(A*A-dy*dy);
				D x=a.X;
				rep(i,2){
					cuts(segs,x-dx,b.X-dx);
					dx=-dx;
				}
			}
//			for(Pi p:segs) printf("(%d,%d),",p.fs,p.sc);
//			puts("");
//			show(segs.size());
		}
		for(Pi p:segs) ans+=p.sc-p.fs+1;
	}
	cout<<ans<<endl;
}
accuracy: 0.1111111111111111
time_ms: 10
memory_kb: 3236
final_rank: 6