Problem:
Problem C:
Area of Polygons
Yoko’s math homework today was to calculate areas of polygons in the
xy
-plane. Vertices are
all aligned to grid points (i.e. they have integer coordinates).
Your job is to help Yoko, not good either at math or at computer programming, get her home-
work done. A polygon is given by listing the coordinates of its vertices. Your program should
approximate its area by counting the number of unit squares (whose vertices are also grid points)
intersecting the polygon. Precisely, a unit square “intersects the polygon” if and only if the in-
tersection of the two has non-zero area. In the figure below, dashed horizontal and vertical lines
are grid lines, and solid lines are edges of the polygon. Shaded unit squares are considered inter-
secting the polygon. Your program should output 55 for this polygon (as you see, the number
of shaded unit squares is 55).
Figure 1: A polygon and unit squares intersecting it
Input
The input file describes polygons one after another, followed by a terminating line that only
contains a single zero.
A description of a polygon begins with a line containing a single integer,
m
(≥ 3), that gives
the number of its vertices. It is followed by
m
lines, each containing two integers
x
and
y
, the coordinates of a vertex. The
x
and
y
are separated by a single space. The
i
-th of these
m
lines
gives the coordinates of the
i
-th vertex (
i
= 1, ... ,
m
). For each
i
= 1, ... ,
m
- 1, the
i
-th vertex
and the (
i
+ 1)-th vertex are connected by an edge. The
m
-th vertex and the first vertex are
also connected by an edge (i.e., the curve is closed). Edges intersect only at vertices. No three
edges share a single vertex (i.e., the curve is simple). The number of polygons is no more than
100. For each polygon, the number of vertices (
m
) is no more than 100. All coordinates
x
and
y
satisfy -2000 ≤
x
≤ 2000 and -2000 ≤
y
≤ 2000.
Output
The output should consist of as many lines as the number of polygons. The
k
-th output line
should print an integer which is the area of the
k
-th polygon, approximated in the way described
above. No other characters, including whitespaces, should be printed.
Sample Input
4
5 -3
1 0
1 7
-7 -1
3
5 5
18 5
5 10
3
-5 -5
-5 -10
-18 -10
5
0 0
20 2
11 1
21 2
2 0
0
Output for the Sample Input
55
41
41
23

Submitted solutions:

code_snippet: #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-8;
struct Point{double x,y;}p[1005];
struct seg{Point A,B;}s[1005];
struct SEG{int x,y;SEG(int _x=0,int _y=0){x=_x;y=_y;}}t[1005];
int N,tt=0;
struct jgt{double x,y,mid;jgt(double _x=0,double _y=0,double _mid=0){x=_x;y=_y;mid=_mid;}}q[1005];
bool operator < (const jgt &x,const jgt &y){return x.mid<y.mid;}
bool operator < (const SEG &x,const SEG &y){return x.x<y.x;}
void Makeseg(Point A,Point B)
{   if(A.x>B.x)swap(A,B);
    tt++;s[tt].A=A;s[tt].B=B;
}
double Abs(double x){if(x<0)x=-x;return x;}
void GetInter(double x)
{   int i;
    Point A,B;
    for(i=1,tt=0;i<=N;i++)
       if(s[i].A.x<=x&&x<=s[i].B.x&&s[i].A.x<=x+1&&x+1<=s[i].B.x&&Abs(s[i].A.x-s[i].B.x)>eps)
         {A=s[i].A;B=s[i].B;
		  q[++tt]=jgt(A.y+(B.y-A.y)/(B.x-A.x)*(x-A.x),A.y+(B.y-A.y)/(B.x-A.x)*(x+1-A.x),A.y+(B.y-A.y)/(B.x-A.x)*(x+0.5-A.x));
		 }
}
int main()
{   int k,i,ans,st,ed;
	while(1)
	  {scanf("%d",&N);
	   if(!N)break;
	   ans=tt=0;
	   for(i=1;i<=N;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
	   for(i=1;i<N;i++)Makeseg(p[i],p[i+1]);
	   Makeseg(p[N],p[1]);
	   for(k=-2000;k<2000;k++)
	     {GetInter(k);
	      if(!tt)continue;
	      sort(q+1,q+1+tt);
	      for(i=1;i<=tt;i+=2)
	        {t[(i+1)/2]=SEG(floor(min(q[i].x+eps,q[i].y+eps)),ceil(max(q[i+1].x-eps,q[i+1].y-eps)));}
	      tt/=2;
	      sort(t+1,t+1+tt);
	      for(i=1,st=ed=-3005;i<=tt;i++)
	        {if(t[i].x>ed){ans+=ed-st;st=t[i].x;ed=t[i].y;}
	         else if(t[i].y>ed)ed=t[i].y;
			}
		  ans+=ed-st;
		 }
	   printf("%d\n",ans);
	  }
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3352
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
using i64 = long long;
#define rep(i,n) for(i64 i=0; i<(i64)(n); i++)


i64 solve(vector<pair<i64,i64>> A){
    i64 n = A.size();
    A.push_back(A[0]);
    i64 area = 0;
    rep(i,n){
        auto [u,v] = A[i];
        auto [x,y] = A[i+1];
        area += u*y - v*x;
    }
    if(area < 0) reverse(A.begin() + 1, A.end() - 1);
    i64 ans = 0;
    vector<vector<pair<i64,i64>>> que(4000);
    rep(i,n){
        auto [x0, y0] = A[i];
        auto [x1, y1] = A[i+1];
        if(y0 < y1){
            if(x0 <= x1){
                for(i64 y=y0+1; y<=y1; y++){
                    i64 x = (x0 * (y1-y) + x1 * (y-y0) + (y1-y0-1)) / (y1-y0);
                    que[y-1].push_back({x,1});
                }
            } else {
                for(i64 y=y0; y<y1; y++){
                    i64 x = (x0 * (y1-y) + x1 * (y-y0) + (y1-y0-1)) / (y1-y0);
                    que[y].push_back({x,1});
                }
            }
        } else {
            if(x0 <= x1){
                for(i64 y=y1+1; y<=y0; y++){
                    i64 x = (x1 * (y0-y) + x0 * (y-y1)) / (y0-y1);
                    que[y-1].push_back({x,-1});
                }
            } else {
                for(i64 y=y1; y<y0; y++){
                    i64 x = (x1 * (y0-y) + x0 * (y-y1)) / (y0-y1);
                    que[y].push_back({x,-1});
                }
            }
        }
    }
    for(auto& qu : que) if(!qu.empty()){
        sort(qu.begin(), qu.end());
        i64 f = 0;
        //for(auto [u,v] : qu){ cout << "(" << (u-2000) << "," << v << ")"; } cout << endl;
        for(auto [u,v] : qu){
            if(!f) ans -= u;
            f += v;
            if(!f) ans += u;
        }
    }
    return ans;
}

void testcase(){
    i64 N; cin >> N;
    if(N == 0) exit(0);
    vector<pair<i64,i64>> A(N);
    for(auto& [u,v] : A){
        cin >> u >> v;
        u += 2000; v += 2000;
    }
    i64 ans = solve(move(A));
    cout << ans << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(true) testcase();
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 11244
final_rank: 16

code_snippet: /// jajaja
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
using Point = pair<int, int>;

const double EPS = 1e-5;

int main() {
  int n;
  while (cin >> n && n > 0) {
    vector<Point> polygon(n);
    for (auto& p : polygon) cin >> p.x >> p.y;

    int area2 = 0;
    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon[i];
      const Point q = polygon[j];
      area2 += p.x * q.y - p.y * q.x;
    }
    if (area2 < 0) reverse(polygon.begin(), polygon.end());

    unordered_map<int, vector<pair<int, int>>> events_by_y;

    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon[i];
      const Point q = polygon[j];
      if (p.y == q.y) continue;

      const auto [min_y, max_y] = minmax(p.y, q.y);
      const double slope = (p.x - q.x) / (double)(p.y - q.y);

      for (int y = min_y; y < max_y; y++) {
        const double a = p.x + slope * (y - p.y);
        const double b = p.x + slope * (y + 1 - p.y);

        if (p.y > q.y) {
          const int x = floor(min(a, b) + EPS);
          events_by_y[y].emplace_back(x, 1);
        } else {
          const int x = ceil(max(a, b) - EPS);
          events_by_y[y].emplace_back(x, -1);
        }
      }
    }

    int ans = 0;

    for (auto& [_, events] : events_by_y) {
      sort(events.begin(), events.end());

      int count = 0;
      int prev = 0;

      for (const auto& [x, d] : events) {
        if (count == 0) prev = x;
        count += d;
        if (count == 0) ans += x - prev;
      }
    }

    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 70
memory_kb: 7796
final_rank: 13

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

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
while(1) {
    int MAXS = 4010;
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<int> A(N), B(N);
    rep(i,0,N) cin >> A[i] >> B[i], A[i] += 2000, B[i] += 2000;
    auto Calc = [&](int L, int R, double X) -> double {
        return (double)B[L]+((double)(B[R]-B[L])/(double)(A[R]-A[L]))*(X-(double)A[L]);
    };
    auto Calc2 = [&](int L, int R, int X) -> int {
        return B[L]+floor((B[R]-B[L])*(X-A[L]),A[R]-A[L]);
    };
    auto Calc3 = [&](int L, int R, int X) -> int {
        return B[L]+ceil((B[R]-B[L])*(X-A[L]),A[R]-A[L]);
    };
    int ANS = 0;
    rep(i,0,MAXS) {
        vector<pair<double,int>> V;
        rep(j,0,N) {
            int L = j, R = (j+1) % N;
            if (A[L] == A[R]) continue;
            if (A[L] > A[R]) swap(L,R);
            if (!(A[L] <= i && i < A[R])) continue;
            double X = (double)i+0.5;
            V.push_back({Calc(L,R,X),j});
        }
        if (V.empty()) continue;
        sort(ALL(V));
        vector<int> IMOS(MAXS,0);
        rep(j,0,V.size()) {
            int L = V[j].second, R = (L+1) % N;
            if (A[L] > A[R]) swap(L,R);
            if (j % 2 == 0) {
                int Y = min(Calc2(L,R,i),Calc2(L,R,i+1));
                IMOS[Y]++;
            }
            else {
                int Y = max(Calc3(L,R,i),Calc3(L,R,i+1));
                IMOS[Y]--;
            }
        }
        rep(j,0,MAXS-1) IMOS[j+1] += IMOS[j];
        rep(j,0,MAXS) if (IMOS[j] >= 1) ANS++;
    }
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 320
memory_kb: 3372
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
using Point = pair<int, int>;

const double EPS = 1e-5;

int main() {
  int n;
  while (cin >> n && n > 0) {
    vector<Point> polygon(n);
    for (auto& p : polygon) cin >> p.x >> p.y;

    int area2 = 0;
    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon[i];
      const Point q = polygon[j];
      area2 += p.x * q.y - p.y * q.x;
    }
    if (area2 < 0) reverse(polygon.begin(), polygon.end());

    unordered_map<int, vector<pair<int, int>>> events_by_y;

    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon[i];
      const Point q = polygon[j];
      if (p.y == q.y) continue;

      const auto [min_y, max_y] = minmax(p.y, q.y);
      const double slope = (p.x - q.x) / (double)(p.y - q.y);

      for (int y = min_y; y < max_y; y++) {
        const double a = p.x + slope * (y - p.y);
        const double b = p.x + slope * (y + 1 - p.y);

        if (p.y > q.y) {
          const int x = floor(min(a, b) + EPS);
          events_by_y[y].emplace_back(x, 1);
        } else {
          const int x = ceil(max(a, b) - EPS);
          events_by_y[y].emplace_back(x, -1);
        }
      }
    }

    int ans = 0;

    for (auto& [_, events] : events_by_y) {
      sort(events.begin(), events.end());

      int count = 0;
      int prev = 0;

      for (const auto& [x, d] : events) {
        if (count == 0) prev = x;
        count += d;
        if (count == 0) {
          ans += x - prev;
        }
      }
    }

    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 80
memory_kb: 7632
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
using Point = pair<int, int>;

double fix_integer(const double x) { return fabs(round(x) - x) < 1e-6 ? round(x) : x; }

int main() {
  int n;
  while (cin >> n && n > 0) {
    vector<Point> polygon(n);
    for (auto& p : polygon) {
      cin >> p.x >> p.y;
      /*p.x += 10;*/
      /*p.y += 10;*/
      /*p.x += 2000;*/
      /*p.y += 2000;*/
    }

    int area2 = 0;
    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon[i];
      const Point q = polygon[j];
      area2 += p.x * q.y - p.y * q.x;
    }
    if (area2 < 0) reverse(polygon.begin(), polygon.end());

    unordered_map<int, vector<pair<int, int>>> events_by_y;

    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon[i];
      const Point q = polygon[j];
      if (p.y == q.y) continue;

      const auto [min_y, max_y] = minmax(p.y, q.y);
      const double slope = (p.x - q.x) / (double)(p.y - q.y);

      for (int y = min_y; y < max_y; y++) {
        const double a = fix_integer(p.x + slope * (y - p.y));
        const double b = fix_integer(p.x + slope * (y + 1 - p.y));

        if (p.y > q.y) {
          const int x = floor(min(a, b));
          events_by_y[y].emplace_back(x, 1);
        } else {
          const int x = ceil(max(a, b));
          events_by_y[y].emplace_back(x, -1);
        }
      }
    }

    int ans = 0;

    for (auto& [_, events] : events_by_y) {
      /*const auto xs2 = y_events2[y];*/
      /*/*sort(xs1.begin(), xs1.end());*/
      /*/*sort(xs2.begin(), xs2.end());*/
      /*const int n = xs1.size();*/
      /*const int m = xs2.size();*/
      /*assert(n == m);*/
      /**/
      /*vector<pair<int, int>> events;*/
      /**/
      /*for (int i = 0; i < n; i++) {*/
      /*  const auto [l1, l2] = xs1[i];*/
      /*  const int enter = floor(min(l1, l2));*/
      /*  events.emplace_back(enter, 1);*/
      /**/
      /*  const auto [r1, r2] = xs2[i];*/
      /*  const int exit = ceil(max(r1, r2));*/
      /*  events.emplace_back(exit, -1);*/
      /*}*/

      sort(events.begin(), events.end());

      int count = 0;
      int prev = 0;

      for (const auto& [x, d] : events) {
        if (count == 0) prev = x;
        count += d;
        if (count == 0) {
          ans += x - prev;
        }
      }
      assert(count == 0);
    }

    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 100
memory_kb: 7800
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
using Point = pair<int, int>;

double fix_integer(const double x) { return fabs(round(x) - x) < 1e-6 ? round(x) : x; }

int main() {
  int n;
  while (cin >> n && n > 0) {
    /*cerr << "------------------" << endl;*/
    vector<Point> polygon(n);
    for (auto& p : polygon) {
      cin >> p.x >> p.y;
      p.x += 10;
      p.y += 10;
      /*p.x += 2000;*/
      /*p.y += 2000;*/
    }

    // todo: it shouldn't be necessary to make it clock-wise.
    int area = 0;
    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon[i];
      const Point q = polygon[j];
      area += p.x * q.y - p.y * q.x;
    }
    if (area < 0) reverse(polygon.begin(), polygon.end());

    /*cerr << "polygon(";*/
    /*bool fuck = false;*/
    /*for (const Point& p : polygon) {*/
    /*  if (fuck) cerr << ",";*/
    /*  cerr << "(" << p.x << "," << p.y << ")";*/
    /*  fuck = true;*/
    /*}*/
    /*cerr << ")" << endl;*/

    unordered_map<int, vector<pair<double, double>>> y_events;
    unordered_map<int, vector<pair<double, double>>> y_events2;

    for (int i = 0; i < (int)polygon.size(); i++) {
      const Point p = polygon[i];
      const Point q = polygon[(i + 1) % polygon.size()];
      if (p.y == q.y) continue;

      const auto [min_y, max_y] = minmax(p.y, q.y);
      const double slope = (p.x - q.x) / (double)(p.y - q.y);

      for (int y = min_y; y < max_y; y++) {
        if (p.y > q.y) {
          y_events[y].emplace_back(fix_integer(p.x + slope * (y - p.y)),
                                   fix_integer(p.x + slope * (y + 1 - p.y)));
        } else {
          y_events2[y].emplace_back(fix_integer(p.x + slope * (y - p.y)),
                                    fix_integer(p.x + slope * (y + 1 - p.y)));
        }
      }
    }

    int ans = 0;

    for (auto& [y, xs1] : y_events) {
      const auto xs2 = y_events2[y];
      /*sort(xs1.begin(), xs1.end());*/
      /*sort(xs2.begin(), xs2.end());*/
      const int n = xs1.size();
      const int m = xs2.size();
      assert(n == m);

      vector<pair<int, int>> events;

      for (int i = 0; i < n; i++) {
        const auto [l1, l2] = xs1[i];
        const int enter = floor(min(l1, l2));
        events.emplace_back(enter, 1);

        const auto [r1, r2] = xs2[i];
        const int exit = ceil(max(r1, r2));
        events.emplace_back(exit, -1);
      }

      sort(events.begin(), events.end());

      int count = 0;
      int prev = 0;

      for (const auto& [x, d] : events) {
        if (count == 0) prev = x;
        /*cerr << y << " " << x << " " << d << endl;*/
        count += d;
        /*assert(count >= 0);*/
        if (count == 0) {
          /*fprintf(stderr, "polygon((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n", prev, y, x, y,
           * x,*/
          /*        y + 1, prev, y + 1);*/
          ans += x - prev;
        }
      }
      /*assert(count == 0);*/
    }

    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 130
memory_kb: 12288
final_rank: 18

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	long double px, py;
};

long double Intersect(Point p1, Point p2, long double ux) {
	if (p1.px > p2.px) swap(p1, p2);
	if (ux <= p1.px || p2.px <= ux) return -1e9;
	long double perc = (ux - p1.px) / (p2.px - p1.px);
	return p1.py + (p2.py - p1.py) * perc;
}

int N;
Point G[109];

int overlap(vector<pair<int, int>> L1) {
	vector<int> Zahyou;
	for (int i = 0; i < L1.size(); i++) Zahyou.push_back(L1[i].first);
	for (int i = 0; i < L1.size(); i++) Zahyou.push_back(L1[i].second);
	sort(Zahyou.begin(), Zahyou.end());
	Zahyou.erase(unique(Zahyou.begin(), Zahyou.end()), Zahyou.end());

	// Imos Method
	vector<int> sum(Zahyou.size() + 2, 0);
	for (int i = 0; i < L1.size(); i++) {
		int pos1 = lower_bound(Zahyou.begin(), Zahyou.end(), L1[i].first) - Zahyou.begin();
		int pos2 = lower_bound(Zahyou.begin(), Zahyou.end(), L1[i].second) - Zahyou.begin();
		sum[pos1] += 1;
		sum[pos2] -= 1;
	}
	for (int i = 1; i <= Zahyou.size(); i++) sum[i] += sum[i - 1];

	// Return
	int Return = 0;
	for (int i = 0; i < Zahyou.size(); i++) {
		if (sum[i] == 0) continue;
		Return += (Zahyou[i + 1] - Zahyou[i]);
	}
	return Return;
}

int solve() {
	int Answer = 0;
	for (int i = -2000; i <= 1999; i++) {
		vector<long double> P1, P2;
		for (int j = 0; j < N; j++) {
			long double r1 = Intersect(G[j], G[(j + 1) % N], 1.0L * i + 0.00001L);
			long double r2 = Intersect(G[j], G[(j + 1) % N], 1.0L * i + 0.99999L);
			if (r1 >= -1e8) P1.push_back(r1);
			if (r2 >= -1e8) P2.push_back(r2);
		}
		if (P1.size() == 0 && P2.size() == 0) continue;
		sort(P1.begin(), P1.end());
		sort(P2.begin(), P2.end());
		vector<pair<int, int>> L1;
		for (int j = 0; j < P1.size(); j += 2) {
			int cl = (int)(P1[j + 0] + 3000.0L);
			int cr = (int)(P1[j + 1] + 3000.0L + 0.999999999L);
			int dl = (int)(P2[j + 0] + 3000.0L);
			int dr = (int)(P2[j + 1] + 3000.0L + 0.999999999L);
			L1.push_back(make_pair(min(cl, dl), max(cr, dr)));
		}
		Answer += overlap(L1);
	}
	return Answer;
}

int main() {
	while (true) {
		cin >> N; if (N == 0) break;
		for (int i = 0; i < N; i++) cin >> G[i].px >> G[i].py;
		cout << solve() << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 3328
final_rank: 5

code_snippet: //#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
//vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
template<typename T> vector<T> inv_perm(const vector<T>&ord){
  vector<T>inv(ord.size());
  for(int i=0;i<ord.size();i++)inv[ord[i]] = i;
  return inv;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
ll modulo(ll n,ll d){return (n%d+d)%d;};
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}

template <typename F>
class
#if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
  [[nodiscard]]
#endif  // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
FixPoint final : private F
{
public:
  template <typename G>
  explicit constexpr FixPoint(G&& g) noexcept
    : F{std::forward<G>(g)}
  {}

  template <typename... Args>
  constexpr decltype(auto)
  operator()(Args&&... args) const
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
  noexcept(noexcept(F::operator()(std::declval<FixPoint>(), std::declval<Args>()...)))
#endif  // !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
  {
    return F::operator()(*this, std::forward<Args>(args)...);
  }
};  // class FixPoint


#if defined(__cpp_deduction_guides)
template <typename F>
FixPoint(F&&)
-> FixPoint<std::decay_t<F>>;
#endif  // defined(__cpp_deduction_guides)


namespace
{
  template <typename F>
#if !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
  #  if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
  __attribute__((warn_unused_result))
#  elif defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_Check_return_)
  _Check_return_
#  endif  // defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#endif  // !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
  inline constexpr decltype(auto)
  makeFixPoint(F&& f) noexcept
  {
    return FixPoint<std::decay_t<F>>{std::forward<std::decay_t<F>>(f)};
  }
}  // namespace

using Real = long double;
using Point = complex<Real>;
const Real EPS = 1e-10, PI = acos((Real)(-1.0));

inline bool eq(Real a, Real b) { return fabs(b - a) < EPS; }
inline bool eq(Point a, Point b) { return fabs(b - a) < EPS; }

Point operator*(const Point &p, const Real &d) {
  return Point(real(p) * d, imag(p) * d);
}

istream &operator>>(istream &is, Point &p) {
  Real a, b;
  is >> a >> b;
  p = Point(a, b);
  return is;
}

ostream &operator<<(ostream &os, Point &p) {
  return os << fixed << setprecision(10) << p.real() << " " << p.imag();
}

Point rotate(Real theta, const Point &p) {
  return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

namespace std {
  bool operator<(const Point& a, const Point& b) {
    return !eq(a.real(), b.real()) ? a.real() < b.real() : a.imag() < b.imag();
  }
}

struct Line {
  Point a, b;
  Line() = default;
  Line(Point a, Point b): a(a), b(b) {}

  friend ostream &operator<<(ostream &os, Line &p) {
    return os << p.a << " to " << p.b;
  }

  friend istream &operator>>(istream &is, Line &a) {
    return is >> a.a >> a.b;
  }
};

struct Circle {
  Point c;
  Real r;
  Circle() = default;
  Circle(Point c, Real r): c(c), r(r) {}

  friend ostream &operator<<(ostream &os, Circle &c) {
    return os << c.c << ": " << c.r;
  }

  friend istream &operator>>(istream &is, Circle &c) {
    return is >> c.c >> c.r;
  }
};

Real cross(const Point &a, const Point &b) {
  return real(a) * imag(b) - real(b) * imag(a);
}

Real dot(const Point &a, const Point &b) {
  return real(a) * real(b) + imag(a) * imag(b);
}

struct Segment : Line {
  Segment() = default;
  Segment(Point a, Point b) : Line(a, b) {}
};

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

bool intersect(const Segment &s, const Point &p) {
  return ccw(s.a, s.b, p) == 0;
}

bool intersect(const Segment &s, const Segment&t) {
  return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool intersect(const Line &l, const Segment& s) {
  return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

int intersect(const Circle &c, const Circle &d) {
  Real dis = fabs(c.c - d.c);

  if (dis > c.r + d.r + EPS) return 4;
  else if (eq(dis, c.r + d.r)) return 3;
  else if (eq(dis, abs(c.r - d.r))) return 1;
  else if (dis + min(c.r, d.r) < max(c.r, d.r) - EPS) return 0;
  else return 2;
}

bool parallel(const Line &a, const Line &b) {
  return abs(cross(a.b - a.a, b.b - b.a)) < EPS;
}

bool orthogonal(const Line &a, const Line &b) {
  return abs(dot(a.b - a.a, b.b - b.a)) < EPS;
}

Point projection(const Line& s, const Point &p) {
  double t = dot(p - s.a, s.b - s.a) / norm(s.b - s. a);
  return s.a + (s.b - s.a) * t;
}

Point projection(const Segment& l, const Point &p) {
  return projection(Line(l), p);
}

Point reflection(const Line &l, const Point &p) {
  Point r = projection(l, p);
  return p + (r - p) * 2;
}

Real distance(const Line &l, const Point &p) {
  Point r = projection(l, p);
  return fabs(p - r);
}

Real distance(const Segment&s, const Point &p) {
  Point r = projection(s, p);
  if (intersect(s, r)) return abs(r - p);
  return min(abs(s.a - p), abs(s.b - p));
}

Real distance(const Segment& a, const Segment& b) {
  if (intersect(a, b)) return 0;
  return min({
               distance(a, b.a),
               distance(a, b.b),
               distance(b, a.a),
               distance(b, a.b)
             });
}

bool contains(const Circle &c, const Point &p) {
  if (fabs(c.c - p) < c.r + EPS) return true;
  return false;
}

Point crosspoint(const Line &l, const Line &m) {
  Real A = cross(l.b - l.a, m.b - m.a);
  Real B = cross(l.b - l.a, l.b - m.a);
  if (eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
  return m.a + (m.b - m.a) * B / A;
}

Point crosspoint(const Segment& l, const Segment& m) {
  return crosspoint(Line(l), Line(m));
}

Line bisector_of_angle(const Point& a, const Point& b, const Point& c) {
  Real d_ab = fabs(a - b);
  Real d_bc = fabs(b - c);
  Point c_ = b + (c - b) * d_ab / d_bc;

  return Line(b, (a + c_) * 0.5);
}

Line bisector(const Point& a, const Point& b) {
  Point c = (a + b) * 0.5;
  Point d = c + rotate(PI / 2, b - c);

  return Line(c, d);
}

int intersect(const Circle &c, const Line &l) {
  Real d = distance(l, c.c);

  if (d > c.r + EPS) return 0;
  if (eq(d, c.r)) return 1;
  return 2;
}

pair<Point, Point> crosspoint(const Circle& c, const Line& l) {
  Real d = distance(l, c.c);

  Point p = projection(l, c.c);
  if (intersect(c, l) == 1) return { p, p };

  Real d2 = sqrt(c.r * c.r - d * d);
  Point v = (l.a - l.b) * (1.0 / fabs(l.a - l.b));

  return { p + d2 * v, p - d2 * v };
}

vector<Point> crosspoint(const Circle &c, const Segment &s) {
  int isect = intersect(c, Line(s));
  if (isect == 0) return {};

  auto [p1, p2] = crosspoint(c, Line(s));

  vector<Point> res;
  if (ccw(s.a, s.b, p1) == 0) res.push_back(p1);
  if (ccw(s.a, s.b, p2) == 0) res.push_back(p2);

  if (res.size() == 2 && ccw(s.a, p1, p2) == 0) swap(res[0], res[1]);
  return res;
}

pair<Point, Point> crosspoint(const Circle &c1, const Circle &c2) {
  Real d = fabs(c1.c - c2.c);
  Real x1 = (c1.r * c1.r + d * d - c2.r * c2.r) / 2 / d;
  Real y = sqrt(c1.r * c1.r - x1 * x1);

  Point base = (c2.c * x1 + c1.c * (d - x1)) * (1.0 / d);
  Point v = rotate(PI / 2, c1.c - base);
  v = v / fabs(v);

  return { base + v * y, base - v * y };
}

pair<Point, Point> tangent(const Circle &c, const Point &p) {
  Real d = fabs(c.c - p);
  Real d2 = sqrt(d * d - c.r * c.r);
  Real a = acos(d2 / d);


  Point q = c.c - p;
  q = q / fabs(q);

//  cout << d << " " << d2 << " " << a << " " << q << endl;
  return {
    p + rotate(a, q) * d2,
    p + rotate(-a, q) * d2
  };
}

vector<Segment> common_tangent(Circle c1, Circle c2) {
  int isect = intersect(c1, c2);
  Real d = fabs(c1.c - c2.c);
  Point v = (c2.c - c1.c) / d;

  vector<Segment> res;

  if (isect == 0) {
    return {};
  } else if (isect == 1) {
    auto [p1, p2] = crosspoint(c1, Line(c1.c, c2.c));
    if (eq(fabs(p2 - c2.c), c2.r)) swap(p1, p2);

    Point v = p1 + rotate(PI/2, c2.c - p1);
    return { Segment(p1, v) };
  } else if (isect == 2) {
  } else if (isect == 3) {
    auto [p1, p2] = crosspoint(c1, c2);
    res.emplace_back(p1, rotate(PI / 2, c1.c - p1) + p1);
  } else {
    Real a = d * c1.r / (c1.r + c2.r);
    Point p = c1.c + v * a;

    Real d1 = sqrt(a * a - c1.r * c1.r), d2 = sqrt(norm(p - c2.c) - c2.r * c2.r);
    Real theta = acos(d1 / a);

//    cout << d << endl;
//    cout << a << " " << d1 << " " << d2 << " " << theta << ": " << p << endl;

    Point e = (c1.c - p) * (1.0 / fabs(c1.c - p));
    Point e1 = rotate(theta, e), e2 = rotate(-theta, e);

    res.emplace_back(p + e1 * d1, p - e1 * d2);
    res.emplace_back(p + e2 * d1, p - e2 * d2);
  }

  if (eq(c1.r, c2.r)) {
    Point e = rotate(PI / 2, v);
    res.push_back(Segment(c1.c + e * c1.r, c2.c + e * c1.r));
    res.push_back(Segment(c1.c - e * c1.r, c2.c - e * c1.r));
    return res;
  }

  if (c1.r > c2.r) swap(c1, c2);

  v = c1.c - c2.c;
  Point p = v * (1.0 / (c2.r - c1.r)) * c2.r + c2.c;

  auto [q1, q2] = tangent(c1, p);
  res.emplace_back(q1, crosspoint(c2, Line(p, q1)).first);
  res.emplace_back(q2, crosspoint(c2, Line(p, q2)).first);

  return res;
}

using Polygon = vector<Point>;

istream& operator>>(istream& is, Polygon &p) {
  for (int i = 0; i < p.size(); i++) is >> p[i];
  return is;
}

ostream& operator<<(ostream& os, Polygon &p) {
  for (int i = 0; i < p.size(); i++) os << p[i] << endl;
  return os;
}

Real area(const Polygon& p) {
  Real res = 0;
  for (int i = 0; i < p.size(); i++) {
    res += cross(p[i], p[(i + 1) % p.size()]);
  }
  return abs(res)/2;
}

Real arcarea(const Circle &c, const Point &p1_, const Point &p2_) {
  Point p1 = p1_ - c.c, p2 = p2_ - c.c;
  Real a2 = atan2(imag(p2), real(p2));
  Point p = rotate(-a2, p1);
  Real a1 = atan2(imag(p), real(p));
//  cout << p1 << " " << p2 << " --- " << a2 << " " << a1 << endl;
  return - a1 / 2 * c.r * c.r;
}

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(fabs(cross(a,b)) < EPS and dot(a,b) < EPS) return 1;
    if(a.imag()>b.imag()) swap(a,b);
    if(a.imag() < EPS and EPS < b.imag() and cross(a,b) > EPS ) {
//      cout << a << " --- " << b << ": " << cross(a, b) << endl;
      x = !x;
    }
  }
  return (x?2:0);
}

Polygon convex_hull(Polygon Q) {
  sort(ALL(Q));

  Polygon upper({Q[0]}), lower({Q[0]});

  rep(i, 1, Q.size()) {
    while (upper.size() >= 2) {
      int _ccw = ccw(upper[upper.size() - 2], upper[upper.size() - 1], Q[i]);
      if (_ccw == 1) {
        upper.pop_back();
      } else {
        break;
      }
    }
    if (upper.size() <= 1) {
      upper.push_back(Q[i]);
    } else if (upper.size() > 1) {
      int _ccw = ccw(upper[upper.size() - 2], upper[upper.size() - 1], Q[i]);
      if (_ccw == -1 || _ccw == -2) {
        upper.push_back(Q[i]);
      }
    }
  }
  rep(i, 1, Q.size()) {
    while (lower.size() >= 2) {
      int _ccw = ccw(lower[lower.size() - 2], lower[lower.size() - 1], Q[i]);
      if (_ccw == -1) {
        lower.pop_back();
      } else {
        break;
      }
    }

    if (lower.size() <= 1) {
      lower.push_back(Q[i]);
    } else if (lower.size() > 1) {
      int _ccw = ccw(lower[lower.size() - 2], lower[lower.size() - 1], Q[i]);
      if (_ccw == 1 || _ccw == -2) {
        lower.push_back(Q[i]);
      }
    }
  }

  Polygon ret;

  rep(i, 0, lower.size()) {
    ret.push_back(lower[i]);
//    cout << lower[i] << endl;
  }

//  cout << " | " << endl;

  rrep(i, 0, upper.size()) {
    if (!eq(lower[0], upper[i]) && !eq(lower.back(), upper[i]))
      ret.push_back(upper[i]);
//    cout << upper[i] << endl;
  }

  int start = 0;

//  cout << ret.size() << endl;
  rep(i, 0, ret.size()) {
    if (ret[i].imag() < ret[start].imag() || (eq(ret[i].imag(), ret[start].imag()) && ret[i].real() < ret[start].real())) {
      start = i;
    }
  }

//  cout << ret.size() << endl;
//  rep(i, 0, ret.size()) {
//    auto p = ret[(i + start) % ret.size()];
//    cout << (int)p.real() << " " << (int)p.imag() << endl;
//  }
//
  return ret;
}

Real closest_pair(vector<Point> &pts, int l, int r) {
  int m = (l + r) / 2;
  if (r - l <= 1) {
    return INF;
  } else if (r - l == 2) {
    if (imag(pts[l]) > imag(pts[l + 1])) swap(pts[l], pts[l + 1]);
    return fabs(pts[l] - pts[l + 1]);
  }

  Real mid = pts[m].real();
  Real d = min(closest_pair(pts, l, m), closest_pair(pts, m, r));

  inplace_merge(pts.begin() + l, pts.begin() + m, pts.begin() + r, [](const Point &a, const Point& b) {
    return a.imag() < b.imag();
  });

  vector<Point> ret;

  for (int i = l; i < r; i++) {
    if (fabs(pts[i].real() - mid) >= d) continue;

    for (int j = ret.size() - 1; j >= 0; j--) {
      if (fabs(imag(ret[j]) - imag(pts[i])) >= d) break;
      chmin(d, fabs(ret[j] - pts[i]));
    }

    ret.emplace_back(pts[i]);
  }

  return d;
}

bool contains(const Polygon &a, const Polygon &b) {
  rep(i, 0, b.size()) {
    if (!contains(a, b[i])) return false;
  }
  return true;
}


Real distance(const Polygon &a, const Point &p) {
  if (contains(a, p)) return 0;
  Real res = INF;
  rep(i, 0, a.size()) {
    Segment as(a[i], a[(i + 1) % a.size()]);
    chmin(res, distance(as, p));
  }
  return res;
}

Real distance(const Polygon &a, const Polygon &b) {
//  if (contains(a, b) || contains(b, a)) return 0;
  Real res = INF;
  rep(i, 0, a.size()) chmin(res, distance(b, a[i]));
  rep(i, 0, b.size()) chmin(res, distance(a, b[i]));
  return res;
}

struct Point3d {
  Real x, y, z;
  Point3d() {}
  Point3d(Real x, Real y, Real z): x(x), y(y), z(z) {}
};

Real distance(const Point3d &a, const Point3d &b) {
  return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) + pow(a.z - b.z, 2));
}

void solve(int N) {
  Polygon Q(N);
  cin >> Q;

  using T = tuple<int, int>;
  ll res = 0;
  rep(y, -2000, 2000) {
    Segment low(Point(-3000, y), Point(3000, y)), high(Point(-3000, y + 1), Point(3000, y + 1));

    vector<T> cr;
    rep(i, 0, N) {
      Segment e(Q[i], Q[(i + 1) % N]);
      if (!intersect(low, e) || !intersect(high, e)) continue;

      auto cl = crosspoint(low, e), ch = crosspoint(high, e);
      Real x1 = floor(min(cl.real(), ch.real())), x2 = ceil(max(cl.real(), real(ch)));
      cr.emplace_back(x1, x2);
    }
    sort(ALL(cr));

    int last = -3000;
    for (int j = 0; j < cr.size(); j += 2) {
      auto [l1, r1] = cr[j];
      auto [l2, r2] = cr[j + 1];

      chmax(l1, last);

      res += r2 - l1;

      chmax(last, r2);
    }
  }
  cout << res << endl;
}

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

  cout << fixed << setprecision(10);
  int N, M;
  while (cin >> N&& N) {
    solve(N);
  }
}
accuracy: 1
time_ms: 440
memory_kb: 3476
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

const double eps=1e-7;

struct point{
    double x,y;
    point() {}
    point(double x,double y): x(x), y(y) {}
    point& operator-=(const point &p){
        x -= p.x; y -= p.y;
        return *this;
    }
    point& operator+=(const point &p){
        x += p.x; y += p.y;
        return *this;
    }
    point& operator*=(double d){
        x *= d; y *= d;
        return *this;
    }
    point& operator/=(double d){
        x /= d; y /= d;
        return *this;
    }
    const point operator+ (const point& p) const;
    const point operator- (const point& p) const;
    const point operator* (double d) const;
    const point operator/ (double d) const;
};
const point point::operator+ (const point& p) const{
    point res(*this); return res += p;
}
const point point::operator- (const point& p) const{
    point res(*this); return res -= p;
}
const point point::operator* (double d) const{
    point res(*this); return res *= d;
}
const point point::operator/ (double d) const{
    point res(*this); return res /= d;
}

struct line{
    point A,B;
    line() {}
    line(point A, point B): A(A), B(B) {}
};

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

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

int ccw(point a,point b,point c){
    b={b.x-a.x,b.y-a.y};
    c={c.x-a.x,c.y-a.y};
    if(cross(b,c)>eps)return 1; // a,b,c反時計回り
    if(cross(b,c)<-eps)return -1; // a,b,c時計周り
    if(dot(b,c)<-eps)return 2; // c,a,b 一直線
    if((b.x*b.x+b.y*b.y)<(c.x*c.x+c.y*c.y))return -2; // a,b,c 一直線
    return 0; // a,c,b 一直線
}

// 線分交差判定
// 端点含む場合は等号外す(AOJ-2742)
bool intersect(point a,point b,point c,point d){
    if(ccw(a,b,c)*ccw(a,b,d)<=0 and ccw(c,d,a)*ccw(c,d,b)<=0)return 1;
    else return 0;
}

// 交点の座標を返す
point Crosspoint(point a,point b,point c,point d){
    point cd={d.x-c.x,d.y-c.y};
    point ca={a.x-c.x,a.y-c.y};
    point cb={b.x-c.x,b.y-c.y};
    double d1=abs(cd.x*ca.y-cd.y*ca.x),d2=abs(cd.x*cb.y-cd.y*cb.x);
    double t=d1/(d1+d2);
    return {a.x+(b.x-a.x)*t,a.y+(b.y-a.y)*t};
}

vector<pair<int,int>> v[4040];

int solve(int n){
    vector<point> p(n);
    for(int i=0;i<n;i++){
        cin >> p[i].x >> p[i].y;
        p[i].x += 2000;
        p[i].y += 2000;
    }
    vector<line> e(n);
    for(int i=0;i<n;i++){
        e[i].A = p[i];
        e[i].B = p[(i+1)%n];
        if(e[i].A.y > e[i].B.y) swap(e[i].A,e[i].B);
        for(int j=e[i].A.y;j<e[i].B.y;j++){
            auto p1 = Crosspoint(e[i].A, e[i].B, point(-100,j), point(10000,j));
            auto p2 = Crosspoint(e[i].A, e[i].B, point(-100,j+1), point(10000,j+1));
            int l = min(p1.x,p2.x)+eps;
            int r = max(p1.x,p2.x)+1-eps;
            v[j].push_back({l,r});
        }
    }
    int res = 0;
    for(int y=0;y<4040;y++){
        sort(v[y].begin(), v[y].end());
        int n = v[y].size();
        int r = -1;
        for(int i=1;i<n;i+=2){
            res += v[y][i].second - max(r, v[y][i-1].first);
            r = v[y][i].second;
        }
        v[y].clear();
    }
    return res;
}

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

    int n;
    while(cin >> n,n){
        cout << solve(n) << "\n";
    }
}
accuracy: 1
time_ms: 30
memory_kb: 7644
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    const int M = 2000;

    while (true) {
        int n;
        cin >> n;
        if (n == 0) break;
        vector<pair<ll, ll>> pts(n);
        rep(i,0,n) {
            int x, y;
            cin >> x >> y;
            x += M;
            y += M;
            pts[i] = {x, y};
        }

        auto calc = [&](ll x1, ll y1, ll x2, ll y2, ll x, bool include) {
            ll add = include ? x2-x1-1 : 0;
            if (y1 < y2) {
                return y1 + ((y2-y1)*(x-x1)+add)/(x2-x1);
            } else {
                return y2 + ((y1-y2)*(x2-x)+add)/(x2-x1);
            }
        };

        ll ans0 = 0, ans1 = 0;
        rep(x,0,2*M) {
            vector<int> imos0(2*M+1), imos1(2*M+1);
            rep(i,0,n) {
                int x1, y1, x2, y2;
                tie(x1, y1) = pts[i];
                tie(x2, y2) = pts[(i+1)%n];
                if (x1 <= x && x < x2) {
                    int ya = min(calc(x1, y1, x2, y2, x, false), calc(x1, y1, x2, y2, x+1, false));
                    imos0[0] -= 1;
                    imos0[ya] += 1;
                    int yb = max(calc(x1, y1, x2, y2, x, true), calc(x1, y1, x2, y2, x+1, true));
                    imos1[0] += 1;
                    imos1[yb] -= 1;
                } else if (x2 <= x && x < x1) {
                    int ya = max(calc(x2, y2, x1, y1, x, true), calc(x2, y2, x1, y1, x+1, true));
                    imos0[0] += 1;
                    imos0[ya] -= 1;
                    int yb = min(calc(x2, y2, x1, y1, x, false), calc(x2, y2, x1, y1, x+1, false));
                    imos1[0] -= 1;
                    imos1[yb] += 1;

                }
            }
            rep(i,0,2*M) {
                imos0[i+1] += imos0[i];
                imos1[i+1] += imos1[i];
            }
            rep(i,0,2*M) {
                if (imos0[i] > 0) ++ans0;
                if (imos1[i] > 0) ++ans1;
            }
        }
        cout << max(ans0, ans1) << "\n";
    }
}
accuracy: 1
time_ms: 1400
memory_kb: 3396
final_rank: 15

code_snippet: #include<bits/stdc++.h> 
using namespace std;
using ll=long long int;
//using Int=__int128;
#define ALL(A) A.begin(),A.end()
template<typename T1,typename T2> bool chmin(T1 &a,T2 b){if(a<=b)return 0; a=b; return 1;}
template<typename T1,typename T2> bool chmax(T1 &a,T2 b){if(a>=b)return 0; a=b; return 1;}
template<typename T> constexpr int bitUP(T x,int a){return (x>>a)&1;}
//→　↓　←　↑ 
int dh[4]={0,1,0,-1}, dw[4]={1,0,-1,0};
//右上から時計回り
//int dh[8]={-1,0,1,1,1,0,-1,-1}, dw[8]={1,1,1,0,-1,-1,-1,0};
//long double EPS = 1e-6;
//long double PI = acos(-1);
//const ll INF=(1LL<<62);
const int MAX=(1<<30);
constexpr ll MOD=1000000000+7;
//constexpr ll MOD=998244353;


inline void bin101(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(20);
}

using pii=pair<int,int>;
using pil=pair<int,ll>;
using pli=pair<ll,int>;
using pll=pair<ll,ll>;
using psi=pair<string,int>;
using pis=pair<int,string>;
using psl=pair<string,ll>;
using pls=pair<ll,string>;
using pss=pair<string,string>;

using Graph=vector<vector<int>>;

template<typename T >
struct edge {
	int to;
	T cost;
	edge()=default;
	edge(int to, T cost) : to(to), cost(cost) {}

};
template<typename T>
using WeightGraph=vector<vector<edge<T>>>;

template<typename T>
void CinGraph(int M,WeightGraph<T> &g,bool directed=false,bool index1=true){
    while(M--){
        int s,t;
        T cost;
        cin>>s>>t>>cost;
        if(index1) s--,t--;
        g[s].emplace_back(t,cost);
        if(not directed) g[t].emplace_back(s,cost);
    }
}

void CinGraph(int M,Graph &g,bool directed=false,bool index1=true){
    while(M--){
        int s,t;
        cin>>s>>t;
        if(index1) s--,t--;
        g[s].push_back(t);
        if(not directed) g[t].push_back(s);
    }
}


//0-indexed vector cin
template<typename T>
inline istream &operator>>(istream &is,vector<T> &v) {
    for(size_t i=0;i<v.size();i++) is>>v[i];
	return is;
}
 
//0-indexed vector cin
template<typename T>
inline istream &operator>>(istream &is,vector<vector<T>> &v) {
    for(size_t i=0;i<v.size();i++){
        is>>v[i];
    }
    return is;
}
//vector cout
template<typename T>
inline ostream &operator<<(ostream &os,const vector<T> &v) {
    for(size_t i=0;i<v.size();i++){
        if(i) os<<" ";
        os<<v[i];
    }
    return os;
}
//vector<vector> cout
template<typename T>
inline ostream &operator<<(ostream &os,const vector<vector<T>> &v) {
    for(size_t i=0;i<v.size();i++){
        os<<v[i];
        if(i+1!=v.size()) os<<"\n";
    }
    return os;
}

//Graph out
template<typename T>
inline ostream &operator<<(ostream &os,const Graph &g) {
    for(size_t i=0;i<g.size();i++){
        for(int to:g[i]){
            os<<i<<"->"<<to<<" ";
        }
        os<<endl;
    }
    return os;
}

//WeightGraph out
template<typename T>
inline ostream &operator<<(ostream &os,const WeightGraph<T> &g) {
    for(size_t i=0;i<g.size();i++){
        for(auto e:g[i]){
            os<<i<<"->"<<e.to<<"("<<e.cost<<") ";
        }
        os<<endl;
    }
    return os;
}


//要素数n 初期値x
template<typename T>
inline vector<T> vmake(size_t n,T x){
	return vector<T>(n,x);
}

//a,b,c,x data[a][b][c] 初期値x
template<typename... Args>
auto vmake(size_t n,Args... args){
	auto v=vmake(args...);
	return vector<decltype(v)>(n,move(v));
}
template<typename V,typename T>
void fill(V &v,const T value){
    v=value;
}

template<typename V,typename T>
void fill(vector<V> &vec,const T value){
    for(auto &v:vec) fill(v,value);
}

//pair cout
template<typename T, typename U>
inline ostream &operator<<(ostream &os,const pair<T,U> &p) {
	os<<p.first<<" "<<p.second;
	return os;
}
 
//pair cin
template<typename T, typename U>
inline istream &operator>>(istream &is,pair<T,U> &p) {
	is>>p.first>>p.second;
	return is;
}
 
//ソート
template<typename T>
inline void vsort(vector<T> &v){
    sort(v.begin(),v.end());
}
 
//逆順ソート
template<typename T>
inline void rvsort(vector<T> &v){
	sort(v.rbegin(),v.rend());
}

//1ビットの数を返す
inline int popcount(int x){
	return __builtin_popcount(x);
}
//1ビットの数を返す
inline int popcount(ll x){
	return __builtin_popcountll(x);
}
template<typename T>
inline void Compress(vector<T> &C){
    sort(C.begin(),C.end());
    C.erase(unique(C.begin(),C.end()),C.end());
}
template<typename T>
inline int lower_idx(const vector<T> &C,T value){
    return lower_bound(C.begin(),C.end(),value)-C.begin();
}
template<typename T>
inline int upper_idx(const vector<T> &C,T value){
    return upper_bound(C.begin(),C.end(),value)-C.begin();
}
//時計回りに90度回転
template<typename T>
inline void rotate90(vector<vector<T>> &C){
    vector<vector<T>> D(C[0].size(),vector<T>(C.size()));
    for(int h=0;h<C.size();h++){
        for(int w=0;w<C[h].size();w++){
            D[w][C.size()-1-h]=C[h][w];
        }
    }
    C=D;
}
//補グラフを返す
//i→iのような辺は加えない
Graph ComplementGraph(const Graph &g){
    size_t sz=g.size();
    bool used[sz][sz];
    fill(used[0],used[sz],false);
    for(size_t i=0;i<sz;i++){
        for(int to:g[i]){
            used[i][to]=true;
        }
    }
    Graph ret(sz);
    for(size_t i=0;i<sz;i++){
        for(size_t j=0;j<sz;j++){
            if(used[i][j]) continue;
            if(i==j) continue;
            ret[i].push_back(j);
        }
    }
    return ret;
}
//グラフの分解 secondはある頂点がどこに対応するか id[i]={2,3}のとき,頂点iはret[2][3]に対応
//無効グラフのみに対応
pair<vector<Graph>,vector<pair<int,int>>> GraphDecomposition(const Graph &g){
    vector<pair<int,int>> id(g.size(),pair<int,int>(-1,-1));
    vector<Graph> ret;
    vector<int> now;
    for(size_t i=0;i<g.size();i++){
        if(id[i].first!=-1) continue;
        id[i].first=ret.size();
        id[i].second=0;
        now.push_back(i);
        for(size_t j=0;j<now.size();j++){
            for(int to:g[now[j]]){
                if(id[to].first==-1){
                    id[to].first=ret.size();
                    id[to].second=now.size();
                    now.push_back(to);
                }
            }
        }
        Graph r(now.size());
        for(size_t j=0;j<now.size();j++){
            r[j]=g[now[j]];
            for(int &to:r[j]){
                to=id[to].second;
            }
        }
        ret.push_back(r);
        now.clear();
    }
    return make_pair(ret,id);
}
//0indexを想定
bool OutGrid(ll h,ll w,ll H,ll W){
    return (h>=H or w>=W or h<0 or w<0);
}

void NO(){
    cout<<"NO"<<"\n";
}
void YES(){
    cout<<"YES"<<"\n";
}
void No(){
    cout<<"No"<<"\n";
}
void Yes(){
    cout<<"Yes"<<"\n";
}
namespace overflow{
    template<typename T>
    T max(){
        return numeric_limits<T>::max();
    }
    template<typename T>
    T ADD(T a,T b){
        T res;
        return __builtin_add_overflow(a,b,&res)?max<T>():res;
    }
    template<typename T>
    T MUL(T a,T b){
        T res;
        return __builtin_mul_overflow(a,b,&res)?max<T>():res;
    }
};
using namespace overflow;
struct ModInt{
    using u64=uint_fast64_t;
    u64 a;
    constexpr ModInt() :a(0){}
    constexpr ModInt(ll x) :a((x>=0)?(x%MOD):(x%MOD+MOD) ) {}

    inline constexpr ModInt operator+(const ModInt rhs)const noexcept{
        return ModInt(*this)+=rhs;
    }
    inline constexpr ModInt operator-(const ModInt rhs)const noexcept{
        return ModInt(*this)-=rhs;
    }
    inline constexpr ModInt operator*(const ModInt rhs)const noexcept{
        return ModInt(*this)*=rhs;
    }
    inline constexpr ModInt operator/(const ModInt rhs)const noexcept{
        return ModInt(*this)/=rhs;
    }
    inline constexpr ModInt operator+(const ll rhs) const noexcept{
        return ModInt(*this)+=ModInt(rhs);
    }
    inline constexpr ModInt operator-(const ll rhs)const noexcept{
        return ModInt(*this)-=ModInt(rhs);
    }
    inline constexpr ModInt operator*(const ll rhs)const noexcept{
        return ModInt(*this)*=ModInt(rhs);
    }
    inline constexpr ModInt operator/(const ll rhs)const noexcept{
        return ModInt(*this)/=ModInt(rhs);
    }

    inline constexpr ModInt &operator+=(const ModInt rhs)noexcept{
        a+=rhs.a;
        if(a>=MOD) a-=MOD;
        return *this;
    }
    inline constexpr ModInt &operator-=(const ModInt rhs)noexcept{
        if(rhs.a>a) a+=MOD;
        a-=rhs.a;
        return *this;
    }
    inline constexpr ModInt &operator*=(const ModInt rhs)noexcept{
        a=(a*rhs.a)%MOD;
        return *this;
    }
    inline constexpr ModInt &operator/=(ModInt rhs)noexcept{
        a=(a*rhs.inverse().a)%MOD;
        return *this;
    }
    inline constexpr ModInt &operator+=(const ll rhs)noexcept{
        return *this+=ModInt(rhs);
    }
    inline constexpr ModInt &operator-=(const ll rhs)noexcept{
        return *this-=ModInt(rhs);
    }
    inline constexpr ModInt &operator*=(const ll rhs)noexcept{
        return *this*=ModInt(rhs);
    }
    inline constexpr ModInt &operator/=(const ll rhs)noexcept{
        return *this/=ModInt(rhs);
    }

    inline constexpr ModInt operator=(const ll x)noexcept{
        a=(x>=0)?(x%MOD):(x%MOD+MOD);
        return *this;
    }

    inline constexpr bool operator==(const ModInt p)const noexcept{
        return a==p.a;
    }

    inline constexpr bool operator!=(const ModInt p)const noexcept{
        return a!=p.a;
    }

    inline constexpr ModInt pow(ll N) const noexcept{
        ModInt ans(1LL),p(a);
        while(N>0){
            if(bitUP(N,0)){
                ans*=p;
            }
            p*=p;
            N>>=1;
        }
        return ans;
    }
    inline constexpr ModInt inverse() const noexcept{
        return pow(MOD-2);
    }

};
inline constexpr ModInt operator+(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)+=b;
}
inline constexpr ModInt operator-(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)-=b;
}
inline constexpr ModInt operator*(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)*=b;
}
inline constexpr ModInt operator/(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)/=b;
}
//cout
inline ostream &operator<<(ostream &os,const ModInt &p) {
    return os<<p.a;
}

//cin
inline istream &operator>>(istream &is,ModInt &p) {
    ll t;
    is>>t;
    p=t;
    return is;
}

struct Binominal{
    vector<ModInt> fac,finv,inv; //fac[n]:n! finv:(n!)の逆元
    int sz;
    Binominal(int n=10) :sz(1){
        if(n<=0) n=10;
        init(n);
    }
    inline void init(int n){
        fac.resize(n+1,1);
        finv.resize(n+1,1);
        inv.resize(n+1,1);
        for(int i=sz+1;i<=n;i++){
            fac[i]=fac[i-1]*i;
            inv[i]=MOD-inv[MOD%i]*(MOD/i);
            finv[i]=finv[i-1]*inv[i];
        }
        sz=n;
    }
    //nCk(n,k<=N) をO(1)で求める
    inline ModInt com(int n,int k){
        if(n<k) return ModInt(0);
        if(n<0 || k<0) return ModInt(0);
        if(n>sz) init(n);
        return fac[n]*finv[k]*finv[n-k];
    }
    //nCk(k<=N) をO(k)　で求める 
    inline ModInt rcom(ll n,int k){
        if(n<0 || k<0 || n<k) return ModInt(0);
        if(k>sz) init(k);
        ModInt ret(1);
        for(int i=0;i<k;i++){
            ret*=n-i;
        }
        ret*=finv[k];
        return ret;
    }

    //重複組み合わせ n種類のものから重複を許してk個を選ぶ
    //〇がn個,|がk個
    inline ModInt h(int n,int k){
        return com(n+k-1,k);
    }
};
vector<int> Subset(int S,bool zero=false,bool full=false){
    vector<int> ret;
    int now=(S-1)&S;
    if(full and S){
        ret.push_back(S);
    }
    do{
        ret.push_back(now);
        now=(now-1)&S;
    }while(now!=0);
    if(zero){
        ret.push_back(0);
    }
    return ret;
}
template<typename T>
T SUM(const vector<T> &v,int s,int t){
    chmax(s,0);
    chmin(t,int(v.size())-1);
    if(s>t) return 0;
    if(s==0) return v[t];
    else return v[t]-v[s-1];
}
template<typename T>
void buildSUM(vector<T> &v){
    for(size_t i=1;i<v.size();i++){
        v[i]+=v[i-1];
    }
    return;
}
////////////////////////////
// マクロや型
////////////////////////////

using DD=long double;

const DD EPS=1e-9;
const DD INF=1e50;
const DD PI=acosl(-1.0);
#define EQ(a,b) (abs( (a) - (b) )<EPS) //a==b
#define LS(a,b) ( (a)+EPS<(b) ) //a<b
#define GR(a,b) ( (a)>(b)+EPS ) //a>b
#define LE(a,b) ( (a)<(b)+EPS ) //a<=b
#define GE(a,b) ( (a)>(b)-EPS ) //a>=b

#define X real()
#define Y imag()


//点
using Point=complex<DD>;
istream &operator>>(istream &is, Point &p) {
  DD x,y;
  is>>x>>y;
  p=Point(x,y);
  return is;
}

//点a→点bの線分
//aとbが等しい時、色々バグるから注意!
struct Segment{
    Point a,b;
    Segment()=default;
    Segment(Point a,Point b) :a(a),b(b){}
    Segment(DD ax,DD ay,DD bx,DD by):a(ax,ay),b(bx,by){}
    Segment(DD r,Point a) :a(a),b(a+polar((DD)1.0,r)){} 
};
using Line=Segment;

//円
struct Circle{
    Point p;
    DD r;
    Circle()=default;
    Circle(Point p,DD r):p(p),r(r){}
};

using Polygon=vector<Point>;

////////////////////////////
// 基本計算
////////////////////////////

//度→ラジアン
inline DD torad(const DD deg){return deg*PI/180;}
//ラジアン→度
inline DD todeg(const DD rad){return rad*180/PI;}
//内積 |a||b|cosθ
inline DD dot(const Point &a,const Point &b){return (conj(a)*b).X;}
//外積 |a||b|sinθ
inline DD cross(const Point &a,const Point &b){return (conj(a)*b).Y;}
//ベクトルpを反時計回りにtheta(ラジアン)回転
Point rotate(const Point &p,const DD theta){return p*Point(cos(theta),sin(theta));}

//余弦定理 cos(角度abc(ラジアン))を返す
//長さの対応に注意 ab:辺abの長さ
//verify:https://codeforces.com/gym/102056/problem/F
DD cosine_formula(const DD ab,const DD bc,const DD ca){
    return (ab*ab+bc*bc-ca*ca)/(2*ab*bc);
}

inline bool xy_sort(const Point &a,const Point &b){
    if(a.X+EPS<b.X) return true;
    if(EQ(a.X,b.X) && a.Y+EPS<b.Y) return true;
    return false;
}
inline bool yx_sort(const Point &a,const Point &b){
    if(a.Y+EPS<b.Y) return true;
    if(EQ(a.Y,b.Y) && a.X+EPS<b.X) return true;
    return false;
}
namespace std{
    inline bool operator<(const Point &a,const Point &b)noexcept{
        return xy_sort(a,b);
    }
}
//DDの比較関数
//map<DD,vector<pii>,DDcom>
struct DDcom{
    bool operator()(const DD a, const DD b) const noexcept {
        return a+EPS<b;
    }
};


////////////////////////////
// 平行や直交
////////////////////////////

bool isOrthogonal(const Point &a,const Point &b){
    return EQ(dot(a,b),0.0);
}
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool isOrthogonal(const Segment &s,const Segment &t){
    return EQ(dot(s.a-s.b,t.a-t.b),0.0);
}
bool isParallel(const Point &a,const Point &b){
    return EQ(cross(a,b),0.0);
}
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool isParallel(const Segment &s,const Segment &t){
    return EQ(cross(s.a-s.b,t.a-t.b),0);
}
//線分a→bに対して点cがどの位置にあるか
//反時計回り:1　時計回り:-1 直線上(a,b,c:-2 a,c,b:0 c,a,b:2)
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
//線分a→bの端点にcがあるなら0と判定されるはず
int ccw(const Point &a,Point b,Point c){
    if(EQ(abs(b-c),0) or EQ(abs(a-c),0)) return 0;
    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(LS(norm(b),norm(c))) return -2;
    return 0;
}

////////////////////////////
// 射影と反射
////////////////////////////

//射影
//直線lに点pから垂線を引いたときの交点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point project(const Point &p,const Line &l){
    Point base=l.b-l.a;
    DD r=dot(p-l.a,base)/norm(base);
    return l.a+base*r;
}
//反射
//直線lに対して点pと対称な点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflect(const Point &p,const Line &l){
    return p+(project(p,l)-p)*(DD)2.0;
}
//反射
//直線lに対して線分sと対称な線分(直線でも使える)
//verify:https://onlinejudge.u-aizu.ac.jp/solutions/problem/1171/review/6009447/bin101/C++17
Segment reflect(const Segment &s,const Line &l){
    return Segment(reflect(s.a,l) , reflect(s.b,l));
}

////////////////////////////
// 点との距離
////////////////////////////

//点と直線の距離
DD DistPL(const Point &p,const Line &l){
    return abs(cross(l.b-l.a,p-l.a))/abs(l.b-l.a);
}
//点と線分の距離
DD DistPS(const Point &p,const Segment &s){
    if( dot(s.b-s.a,p-s.a)<0.0 ) return abs(p-s.a);
    if( dot(s.a-s.b,p-s.b)<0.0 ) return abs(p-s.b);
    return DistPL(p,s);
}

////////////////////////////
// 線分と直線
////////////////////////////

//線分a-b,c-dは交差するか?
//接する場合も交差すると判定
//接する場合は交差しないとするなら<=を<に変換
bool intersect(const Point &a,const Point &b,const Point &c,const Point &d){
    return(ccw(a,b,c)*ccw(a,b,d)<=0 && ccw(c,d,a)*ccw(c,d,b)<=0);
}
//線分s,tは交差するか？
//接する場合も交差すると判定
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B&lang=ja
//接する場合は交差しないとするならintersectの<=を<に変換
bool intersect(const Segment &s,const Segment &t){
    return intersect(s.a,s.b,t.a,t.b);
}
// 2直線の交点
// 線分の場合はintersectをしてから使う
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C&lang=ja
Point crossPoint(const Line &s,const Line &t){
    Point base=t.b-t.a;
    DD d1=cross(base,t.a-s.a);
    DD d2=cross(base,s.b-s.a);
    if(EQ(d1,0) and EQ(d2,0)) return s.a; //同じ直線
    if(EQ(d2,0)) assert(false); //交点がない
    return s.a+d1/d2*(s.b-s.a);
}
//線分と線分の距離
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D&lang=ja
DD Dist(const Segment &s,const Segment &t){
    if(intersect(s,t)) return 0.0;
    return min(min(DistPS(t.a,s),DistPS(t.b,s)),min(DistPS(s.a,t),DistPS(s.b,t)) );
}
bool issame(const Line &l,const Line &m){
    if (GR(abs(cross(m.a - l.a, l.b - l.a)),0) ) return false;
    if (GR(abs(cross(m.b - l.a, l.b - l.a)),0) ) return false;
    return true;
}

////////////////////////////
// 円
////////////////////////////
//直線lと円Cの交点
//l.aにより近い方がindexが小さい
//veirfy:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
vector<Point> crossPointLC(const Line &l,const Circle &c){
    vector<Point> ret;
    if(GR(DistPL(c.p,l),c.r)) return ret; //交点がないとき、空ベクトルを返す
    Point pr=project(c.p,l);
    Point e=(l.b-l.a)/(abs(l.b-l.a));
    DD base=sqrt(c.r*c.r-norm(pr-c.p));
    ret.push_back(pr-e*base);
    ret.push_back(pr+e*base);
    if(EQ(DistPL(c.p,l),c.r)) ret.pop_back(); //接するとき
    return ret;
}
//線分sと円cの交点
//交点がないときは空ベクトルを返す
//線分の端が交わる場合も交点とみなす
//s.aにより近い方がindexが小さい
vector<Point> crossPointSC(const Segment &s,const Circle &c){
    vector<Point> ret;
    if(DistPS(c.p,s)>c.r+EPS) return ret;
    auto koho=crossPointLC(s,c);
    for(auto p:koho){
        if(ccw(s.a,s.b,p)==0 or EQ(abs(p-s.a),0) or EQ(abs(p-s.b),0)) ret.push_back(p);
    }
    return ret;
}

//円aと円bの共通接線の数
//離れている:4 外接:3 交わる:2 内接:1 内包:0
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A
int intersect(const Circle &a,const Circle &b){
    DD d=abs(a.p-b.p);
    if(GR(d,a.r+b.r)) return 4;
    if(EQ(d,a.r+b.r)) return 3;
    if(EQ(d,abs(a.r-b.r))) return 1;
    if(LS(d,abs(a.r-b.r))) return 0;
    return 2;
}

//円aと円bの交点
//交点がないときは空ベクトルを返す
//事前にintersectをしたほうがいいかも
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
vector<Point> crossPoint(const Circle &a,const Circle &b){
    vector<Point> ret;
    if(GR(abs(a.p-b.p),a.r+b.r)) return ret;
    DD d=abs(a.p-b.p);
    DD s=acosl((a.r*a.r+d*d-b.r*b.r)/(2*a.r*d)); //0~π
    DD t=arg(b.p-a.p);
    if(EQ(a.r+b.r,d)) ret.push_back(a.p+polar(a.r,t));
    else ret.push_back(a.p+polar(a.r,t+s)),ret.push_back(a.p+polar(a.r,t-s));
    return ret;
}

//点pから円cに接線を引いたときの接点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F&lang=ja
vector<Point> TanLine(const Point &p,const Circle &c){
    vector<Point> ret;
    DD d=abs(p-c.p);
    if(LS(d,c.r)) return ret; //pがcの内部にある場合
    if(EQ(d,c.r)){
        ret.push_back(p);
        return ret; //円の線上にある場合
    } 
    return crossPoint(c,Circle(p,sqrt(d*d-c.r*c.r)));
}

//円a,bの共通接線
//https://www.slideshare.net/kujira16/ss-35861169
//Line.aは円aと接線の交点
//(接線と円bの交点)と(接線と円aの交点)が違う場合はLine.bは(接線と円bの交点)
//一致する場合は円aの中心からLine.aに向かうベクトルを反時計回りに90度回転したものを
//Line.aに足したもの
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2201
vector<Line> TanLine(const Circle &a,const Circle &b){
    DD d=abs(a.p-b.p);
    vector<Line> ret;
    //外接線
    if(intersect(a,b)>=2){
        if(EQ(a.r,b.r)){
            Point up=polar(a.r,arg(b.p-a.p)+PI/2);
            ret.emplace_back(a.p+up,b.p+up);
            ret.emplace_back(a.p-up,b.p-up);
        }else{
            Point q=(a.p*b.r-b.p*a.r)/(b.r-a.r);
            auto as=TanLine(q,a);
            auto bs=TanLine(q,b);
            assert(as.size()==2 and bs.size()==2);
            for(int i=0;i<2;i++){
                ret.emplace_back(as[i],bs[i]);
            }
        }
    }else if(intersect(a,b)==1){ //内接する場合
        Point dir;
        if(a.r>b.r) dir=polar(a.r,arg(b.p-a.p));
        else dir=polar(a.r,arg(a.p-b.p));
        ret.emplace_back(a.p+dir,a.p+dir+rotate(dir,PI/2));
    }
    //内接線
    if(GR(abs(a.p-b.p),a.r+b.r)){ //円が離れている場合
        Point q=a.p+(b.p-a.p)*a.r/(a.r+b.r);
        auto as=TanLine(q,a);
        auto bs=TanLine(q,b);
        assert(as.size()==2 and bs.size()==2);
        for(int i=0;i<2;i++){
            ret.emplace_back(as[i],bs[i]);
        }
    }else if(EQ(d,a.r+b.r)){ //円が接している場合
        Point dir=polar(a.r,arg(b.p-a.p));
        ret.emplace_back(a.p+dir,a.p+dir+rotate(dir,PI/2));
    }
    return ret;
}
//２つの円の共通部分の面積
//参考: https://tjkendev.github.io/procon-library/python/geometry/circles_intersection_area.html
//verify: https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6005736#1
DD Area(const Circle &c1,const Circle &c2){
    DD cd=abs(c1.p-c2.p);
    if(LE(c1.r+c2.r,cd)) return 0; //円が離れている

    if(LE(cd,abs(c1.r-c2.r))) //片方の円が他方を包んでいる
        return min(c1.r,c2.r)*min(c1.r,c2.r)*PI;

    DD theta1=acosl(cosine_formula(c1.r,cd,c2.r));
    DD theta2=acosl(cosine_formula(c2.r,cd,c1.r));

    return c1.r*c1.r*theta1+c2.r*c2.r*theta2-c1.r*cd*sin(theta1);
}


////////////////////////////
// 三角形
////////////////////////////

//ヘロンの公式　三角形の面積を返す
//三角形が成立するか(平行ではないか)を忘れずに
DD Heron(const DD ad,const DD bd,const DD cd){
    DD s=(ad+bd+cd)/2;
    return sqrt(s*(s-ad)*(s-bd)*(s-cd));
}
//三角形の外接円
//isParallel()を使って三角形が成立するか(平行ではないか)を忘れずに
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_C
Circle CircumscribedCircle(const Point &a,const Point &b,const Point &c){
    Point bc=(b+c)/(DD)2.0;
    Line aa(bc,bc+rotate(c-b,PI/2));
    Point ab=(a+b)/(DD)2.0;
    Line cc(ab,ab+rotate(b-a,PI/2));
    Point p=crossPoint(aa,cc);
    return Circle(p,abs(a-p));
}
//三角形の内接円
//isParallel()を使って三角形が成立するか(平行ではないか)を忘れずに
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_B
Circle InCircle(const Point &a,const Point &b,const Point &c){
    Line aa(a,a+polar((DD)1.0,(arg(b-a)+arg(c-a))/(DD)2.0));
    Line bb(b,b+polar((DD)1.0,(arg(a-b)+arg(c-b))/(DD)2.0));
    Point p=crossPoint(aa,bb);
    return Circle(p,DistPL(p,Line(a,b)));
}


 

void solve(){
while(true){
    int N; cin>>N;
    if(N==0) return;

    vector<Point> P(N);
    for(auto &p:P) cin>>p;
    vector<Segment> vs;
    for(int i=0;i<N;i++){
        vs.emplace_back(P[i],P[(i+1)%N]);
    }
    int ans=0;
    for(int y=-2000;y<2000;y++){
        vector<pair<DD,DD>> v;
        Segment ys1(Point(-2100,y+1),Point(2100,y+1));
        Segment ys2(Point(-2100,y),Point(2100,y));
        for(auto s:vs){
            if(intersect(s,ys1)==false or intersect(s,ys2)==false){
                continue;
            }
            DD x1=crossPoint(s,ys1).X;
            DD x2=crossPoint(s,ys2).X;
            if(x1>x2) swap(x1,x2);
            v.emplace_back(x1,x2);
        }
        vsort(v);
        int r=-2100;
        for(int i=0;i+1<v.size();i+=2){
            DD x1=v[i].first;
            DD x2=v[i+1].second;
            ans+=ceil(x2-EPS)-max<int>(r,floor(x1+EPS));
            chmax(r,ceil(x2-EPS));
        }
    }
    cout<<ans<<endl;
}
}

int main(){
    bin101();
    int T=1;
    //cin>>T;
    while(T--) solve();
}
accuracy: 1
time_ms: 3440
memory_kb: 3540
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define POPCOUNT(x) __builtin_popcount(x)
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

const ull MOD = 1e9 + 7;

// BEGIN CUT
ll modpow(ll x, ll y, ll m) {
    ll a = 1, p = x;
    while (y > 0) {
        if (y % 2 == 0) {
            p = (p * p) % m;
            y /= 2;
        } else {
            a = (a * p) % m;
            y--;
        }
    }
    return a;
}
// END CUT

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

int main() {
    int n;
    while (cin >> n, n) {
        vector<PII> poly;
        int min_y = 1 << 30, max_y = -(1 << 30);
        for (int i = 0; i < n; i++) {
            int x, y;
            cin >> x >> y;
            poly.emplace_back(x, y);
            chmin(min_y, y);
            chmax(max_y, y);
        }
        int ans = 0;
        for (int Y = min_y; Y < max_y; Y++) {
            vector<pair<double, double>> points;
            for (int i = 0; i < n; i++) {
                auto [x1, y1] = poly[i];
                auto [x2, y2] = poly[(i + 1) % n];
                if (y1 > y2) {
                    swap(x1, x2);
                    swap(y1, y2);
                }
                if (y1 == y2 || y2 < Y + 1 || y1 > Y)
                    continue;
                double cx1 = x1 + 1.0 * (x2 - x1) * (Y - y1) / (y2 - y1);
                double cx2 = x1 + 1.0 * (x2 - x1) * (Y + 1 - y1) / (y2 - y1);
                if (cx1 > cx2)
                    swap(cx1, cx2);
                points.emplace_back(cx1, cx2);
            }
            sort(ALL(points));
            int prev = -(1 << 30);
            for (int i = 0; i + 1 < points.size(); i += 2) {
                int l = max((int)floor(points[i].first), prev);
                int r = ceil(points[i + 1].second);
                ans += r - l;
                prev = r;
            }
        }
        cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 50
memory_kb: 3392
final_rank: 3

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
//const int mod = 1e9 + 7;
const int mod = 998244353;

using tu = tuple<double,double,int>;

int main(){
	while(1){
		int n; cin >> n;
		if(!n) break;
		vl x(n),y(n);
		rep(i,n) cin >> x[i] >> y[i], x[i] += 2000, y[i] += 2000;
		vector<vector<tu>> in(4040);
		vector<set<int>> out(4040);
		rep(i,n){
			int now = i;
			int nxt = (i+1)%n;
			if(x[now] > x[nxt]) swap(now,nxt);
			if(x[now] == x[nxt]) continue;
			in[x[now]].emplace_back(y[now],(double)(y[nxt]-y[now])/(x[nxt]-x[now]),i);
			out[x[nxt]].insert(i);
		}
		set<tu> se;
		ll ans = 0;
		rep(i,4010){
			for(auto p : in[i]){
				se.emplace(p);
			}
			vector<tu> nxt;
			for(auto itr = se.begin(); itr != se.end();){
				if(out[i].count(get<2>(*itr))){
					itr = se.erase(itr);
				}else{
					itr++;
				}
			}
			assert((int)(se.size()) % 2 == 0);
			ll pre = -1;
			while(!se.empty()){
				auto t = *se.begin(); se.erase(se.begin());
				auto u = *se.begin(); se.erase(se.begin());
				double ue = max(get<0>(u), get<0>(u) + get<1>(u));
				double sita = min(get<0>(t), get<0>(t) + get<1>(t));
				if((ll)(floor(sita+eps) + eps) < pre){
					sita = pre;
				}
				ans += (ll)round(ceil(ue-eps) - floor(sita+eps));
				pre = (ll)(ceil(ue-eps) + eps);
				get<0>(t) += get<1>(t);
				get<0>(u) += get<1>(u);
				nxt.emplace_back(t);
				nxt.emplace_back(u);
			}
			for(auto p : nxt) se.emplace(p);
		}
		cout << ans << "\n";
	}
}
accuracy: 1
time_ms: 220
memory_kb: 3428
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double EPS = 0.0000001;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): 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);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
int main(){
  while (true){
    int m;
    cin >> m;
    if (m == 0){
      break;
    }
    vector<int> x(m + 1), y(m + 1);
    vector<point> P(m + 1);
    for (int i = 0; i < m; i++){
      cin >> x[i] >> y[i];
      x[i] += 2000;
      y[i] += 2000;
      P[i] = point(x[i], y[i]);
    }
    x[m] = x[0];
    y[m] = y[0];
    P[m] = P[0];
    vector<vector<pair<int, int>>> R(4000);
    for (int i = 0; i < m; i++){
      int mn = min(y[i], y[i + 1]);
      int mx = max(y[i], y[i + 1]);
      line L(P[i], P[i + 1]);
      for (int j = mn; j < mx; j++){
        line L1(point(0, j), point(5000, j));
        point Q1 = line_intersection(L, L1);
        line L2(point(0, j + 1), point(5000, j + 1));
        point Q2 = line_intersection(L, L2);
        int l = min(Q1.x, Q2.x) + EPS;
        int r = max(Q1.x, Q2.x) + 1 - EPS;
        R[j].push_back(make_pair(l, r));
      }
    }
    int ans = 0;
    for (int i = 0; i < 4000; i++){
      sort(R[i].begin(), R[i].end());
      int cnt = R[i].size();
      int r = -1;
      int tmp = ans;
      for (int j = 0; j < cnt; j++){
        if (j % 2 == 1){
          ans += R[i][j].second - r;
        } else {
          ans += R[i][j].second - max(R[i][j].first, r);
        }
        r = R[i][j].second;
      }
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 80
memory_kb: 6940
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

struct Point {
  int x, y;
};

int n;
Point v[100];
vector<pair<int, int> > table1[4001];
vector<pair<int, int> > table2[4001];

double GetX(const Point& a, const Point& b, double y) {
  static const double epcilon = 0.000000000001;
  double t = (a.x - b.x) * (y - b.y) / (a.y - b.y) + b.x;
  if(ceil(t) - t < epcilon)
    t = ceil(t);
  if(t - floor(t) < epcilon)
    t = ceil(t);
  return t;
}

void Add(const Point& a, const Point& b) {
  double x1, x2;
  if(a.y < b.y) {
    for(int y = a.y; y < b.y; ++y) {
      x1 = GetX(a, b, y);
      x2 = GetX(a, b, y+1);
      if(a.x > b.x)
	swap(x1, x2);
      table1[y+2000].push_back(make_pair((int)floor(x1), 1));
      table2[y+2000].push_back(make_pair((int)ceil(x2), 1));
    }
  } else {
    for(int y = b.y; y < a.y; ++y) {
      x1 = GetX(a, b, y);
      x2 = GetX(a, b, y+1);
      if(a.x > b.x)
	swap(x1, x2);
      table1[y+2000].push_back(make_pair((int)ceil(x1), -1));
      table2[y+2000].push_back(make_pair((int)floor(x2), -1));
    }
  }
}

int CountT(vector<pair<int, int> >& t) {
  sort(t.begin(), t.end());
  int cnt = 0;
  int state = 0;
  int prev;
  for(vector<pair<int, int> >::iterator p = t.begin(); p != t.end(); ++p) {
    if(state)
      cnt += p->first - prev;
    state += p->second;
    prev = p->first;
  }
  return cnt;
}

int Count() {
  int c1 = 0;
  int c2 = 0;
  for(int i = 0; i < 4001; ++i) {
    c1 += CountT(table1[i]);
    c2 += CountT(table2[i]);
  }
  return max(c1, c2);
}

int main() {
  while(cin >> n && n) {
    for(int i = 0; i < 4001; ++i) {
      table1[i].clear();
      table2[i].clear();
    }
    for(int i = 0; i < n; ++i) {
      cin >> v[i].x >> v[i].y;
      if(i)
	Add(v[i-1], v[i]);
    }
    Add(v[n-1], v[0]);
    cout << Count() << endl;
  }
}
accuracy: 1
time_ms: 170
memory_kb: 11280
final_rank: 17

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


#define NUM 105

int N;

struct Point{

	void set(int arg_x,int arg_y){
		x = arg_x;
		y = arg_y;
	}
	int x,y;
};

struct Edge{
	Edge(int arg_left,int arg_right){
		left = arg_left;
		right = arg_right;
	}
	bool operator<(const struct Edge &arg) const{
		if(left != arg.left){

			return left < arg.left;

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

//http://www.ipsj.or.jp/07editj/promenade/4501.pdf

Point point[NUM];

void compute_x(int i,int y,int *xl,int *xr){

	int den,num,w;

	den =  point[i+1].y-point[i].y;
	num = (y-point[i].y)*(point[i+1].x-point[i].x);
	w = point[i].x+num/den;

	if(num%den == 0){
		*xl = w;
		*xr = w;
	}
	else if((num%den)*den < 0){
		*xl = w-1;
		*xr = w;
	}else{
		*xl = w;
		*xr = w+1;
	}
}

int calc_S(int under_y){

	vector<Edge> V;
	int xla,xra,xlb,xrb;

	//under_y～under_y+1を走る辺を求める
	for(int i = 0; i < N; i++){
		if((point[i].y <= under_y && point[i+1].y <= under_y) ||
			(point[i].y >= under_y+1 && point[i+1].y >= under_y+1))continue;

		compute_x(i,under_y,&xla,&xra); //y == yとの交点
		compute_x(i,under_y+1,&xlb,&xrb); //y == y+1との交点

		V.push_back(Edge(min(xla,xlb),max(xra,xrb)));
	}

	sort(V.begin(),V.end());

	int prev = -2000,ret = 0;

	for(int i = 0; i < V.size(); i += 2){
		ret += V[i+1].right-max(V[i].left,prev);
		prev = V[i+1].right;
	}

	return ret;
}

void func(){

	int y_min = BIG_NUM,y_max = -BIG_NUM;

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

		scanf("%d %d",&point[i].x,&point[i].y);

		//入力のついでにy座標の最大値と最小値を求める
		y_min = min(y_min,point[i].y);
		y_max = max(y_max,point[i].y);
	}
	point[N] = point[0];

	int ans = 0;

	for(int under_y = y_min; under_y <= y_max-1; under_y++){

		ans += calc_S(under_y);
	}

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

int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3160
final_rank: 1

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int N;
int X[100],Y[100];
void f(int sx,int sy,int gx,int gy,vector<pair<int,int> >&ed)
{
	if(sy==gy)return;
	if(sx>gx)
	{
		f(gx,gy,sx,sy,ed);
		return;
	}
	int dx=gx-sx,dy=gy-sy;
	for(int i=0;i<dx;i++)
	{
		if(dy>0)
		{
			int A=i*dy/dx,B=((i+1)*dy-1)/dx;
			for(;A<=B;A++)ed.push_back(make_pair(sx+i,sy+A));
		}
		else
		{
			int A=i*dy/dx-1,B=((i+1)*dy+1)/dx-1;
			for(;A>=B;A--)ed.push_back(make_pair(sx+i,sy+A));
		}
	}
}
long gcd(long a,long b){return b?gcd(b,a%b):a;}
struct rat{
	long a,b;
	rat(long a_,long b_){
		long g=gcd(a_,b_);
		a=a_/g;
		b=b_/g;
		if(b<0)
		{
			a=-a;
			b=-b;
		}
	}
	rat operator*(long x)const{
		return rat(a*x,b);
	}
	rat operator+(long x)const{
		return rat(a+b*x,b);
	}
	bool operator<(const rat&r)const
	{
		return a*r.b<b*r.a;
	}
	long floor()const{return a/b;}
	long ceil()const{return(a+b-1)/b;}
};
main()
{
	while(cin>>N,N)
	{
		for(int i=0;i<N;i++)
		{
			cin>>X[i]>>Y[i];
			X[i]+=2000;
			Y[i]+=2000;
		}
		int ans=0;
		vector<pair<int,int> >ed;
		for(int i=0;i<N;i++)
		{
			int j=(i+1)%N;
			if(X[i]==X[j])continue;
			f(X[i],Y[i],X[j],Y[j],ed);
		}
		for(int x=0;x<4000;x++)
		{
			vector<pair<rat,rat> >y;
			for(int i=0;i<N;i++)
			{
				int j=(i+1)%N;
				if(X[i]<=x&&x+1<=X[j])
				{
					int dx=X[j]-X[i];
					int dy=Y[j]-Y[i];
					rat now(dy,dx);
					y.push_back(make_pair(
						now*(x-X[i])+Y[i],
						now*(x+1-X[i])+Y[i]
					));
				}
				else if(X[j]<=x&&x+1<=X[i])
				{
					int dx=X[i]-X[j];
					int dy=Y[i]-Y[j];
					rat now(dy,dx);
					y.push_back(make_pair(
						now*(x-X[j])+Y[j],
						now*(x+1-X[j])+Y[j]
					));
				}
			}
			sort(y.begin(),y.end());
			if(y.size()%2==1)cout<<"ERROR"<<endl;
			for(int i=0;i<y.size();i+=2)
			{
				long L=max(y[i].first.ceil(),y[i].second.ceil());
				long R=min(y[i+1].first.floor(),y[i+1].second.floor());
				if(R>L)ans+=R-L;
			}
		}
		sort(ed.begin(),ed.end());
		ed.erase(unique(ed.begin(),ed.end()),ed.end());
		ans+=ed.size();
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 2040
memory_kb: 15400
final_rank: 20

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

struct  Point {
	long double x;
	long double y;
	Point(long double xx, long double yy) {
		x = xx, y = yy;
	}
	Point() {
	}
	Point operator + (const Point& c)const {
		Point box;
		box.x = x + c.x;
		box.y = y + c.y;
		return box;
	}
	Point operator - (const Point& c)const {
		Point box;
		box.x = x - c.x;
		box.y = y - c.y;
		return box;
	}
	Point operator * (const long double& b)const {
		Point box;
		box.x = x * b;
		box.y = y * b;
		return box;
	}
	bool operator <(const Point& c)const {
		if (y < c.y)return true;
		if (y > c.y)return false;
		if (x < c.x)return true;
		return false;
	}
	bool operator >(const Point& c)const {
		if (y > c.y)return true;
		if (y < c.y)return false;
		if (x > c.x)return true;
		return false;
	}
	long double det(Point a) {
		return x * a.y - y * a.x;
	}
};

struct Line {
	long double a, b, c;
	Line(const int aa, const int bb, const int cc) {
		a = aa, b = bb, c = cc;
	}
	Line(const Point s, const Point t) {
		if (abs(s.x - t.x) < EPS) {
			a = 1;
			b = 0;
		}
		else {
			b = 1;
			a = (t.y - s.y) / (s.x - t.x);
		}
		c = s.x*a + s.y*b;
	}
};

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

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

long double Distance(Point a, Point b) {
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

long double Distance(Point a, pair<Point, Point>b) {
	Line l = Line(b.first, b.second);
	if (abs(l.a*a.x + l.b*a.y - l.c) < EPS) {
		if (abs(Distance(a, b.first) + Distance(a, b.second) - Distance(b.second, b.first)) <= sqrt(EPS))return 0;
		return min(Distance(a, b.first), Distance(a, b.second));
	}
	long double A = pow((b.first.x - b.second.x), 2) + pow((b.first.y - b.second.y), 2);
	long double B = 2 * (a.x - b.first.x)*(b.first.x - b.second.x) + 2 * (a.y - b.first.y)*(b.first.y - b.second.y);
	long double r = B / 2 / A;
	r = -r;
	if (r >= 0 && r <= 1) {
		return Distance(a, Point(b.first.x + r * (b.second.x - b.first.x), b.first.y + r * (b.second.y - b.first.y)));
	}
	else {
		return min(Distance(a, b.first), Distance(a, b.second));
	}
}

bool LineCross(Point a1, Point a2, Point b1, Point b2) {
	return cross(a2 - a1, b1 - a1)*cross(a2 - a1, b2 - a1) < EPS&&cross(b2 - b1, a1 - b1)*cross(b2 - b1, a2 - b1) < EPS && !(abs((a1 - a2).x*(a1 - b1).y - (a1 - a2).y*(a1 - b1).x)<EPS && abs((a1 - a2).x*(a1 - b2).y - (a1 - a2).y*(a1 - b2).x)<EPS&&abs(Distance(a1, a2) - Distance(a1, b1) - Distance(a2, b1)) > EPS&&abs(Distance(a1, a2) - Distance(a2, b2) - Distance(a1, b2)) > EPS&&abs(Distance(b1, b2) - Distance(a1, b1) - Distance(a1, b2)) > EPS&&abs(Distance(b1, b2) - Distance(a2, b1) - Distance(a2, b2)) > EPS);
}

long double Distance(pair<Point, Point>a, pair<Point, Point>b) {
	if (LineCross(a.first, a.second, b.first, b.second))return 0;
	return min({ Distance(a.first,b),Distance(a.second,b),Distance(b.first,a),Distance(b.second,a) });
}

Point LineCross(Line a, Line b) {
	Point ret;
	ret.x = (a.c*b.b - a.b*b.c) / (a.a*b.b - a.b*b.a);
	ret.y = -(a.c*b.a - a.a*b.c) / (a.a*b.b - a.b*b.a);
	return ret;
}

long double TriangleArea(Point a, Point b, Point c) {
	long double A, B, C;
	A = Distance(a, b);
	B = Distance(a, c);
	C = Distance(b, c);
	long double S = (A + B + C) / 2;
	return sqrt(S*(S - A)*(S - B)*(S - C));
}

bool IsPointLeft(pair<Point, Point>a, Point b) {
	a.second = a.second - a.first;
	b = b - a.first;
	a.first = a.first - a.first;
	long double radline = atan2(a.second.y, a.second.x);
	long double radpoint = atan2(b.y, b.x) - radline;
	if (sin(radpoint) >= -EPS)return true;
	else return false;
}

bool IsPointInPolygon(Point p, vector<Point>poly) {
	bool ret = true;
	for (int i = 0; i < poly.size(); i++) {
		if (Distance(p, { poly[i],poly[(i + 1) % poly.size()] }) <= EPS) return true;
		ret &= IsPointLeft({ poly[i],poly[(i + 1) % poly.size()] }, p);
	}
	return ret;
}

long double Area(vector<Point>p) {
	long double ret = 0;
	for (int i = 2; i < p.size(); i++) {
		ret += TriangleArea(p[0], p[i - 1], p[i]);
	}
	return ret;
}

vector<vector<Point>>DividePolygonByLine(vector<Point>p, pair<Point, Point>l) {
	vector<int>cr;
	vector<Point>cp;
	for (int k = 0; k < p.size(); k++) {
		int nx = k + 1;
		nx %= p.size();
		if (LineCross(p[k], p[(k + 1) % p.size()], l.first, l.second)) {
			auto np = LineCross(Line(p[k], p[(k + 1) % p.size()]), Line(l.first, l.second));
			bool flag = true;
			for (auto l : cp) {
				if (Distance(l, np) <= EPS)flag = false;
			}
			if (flag) {
				cr.push_back(k);
				cp.push_back(np);
			}
		}
	}
	vector<Point>w;
	vector<Point>x;
	if (cr.size() != 2)return vector<vector<Point>>(1, p);
	int cnt = cr[0];
	do {
		if (w.empty() || Distance(w.back(), p[cnt]) > EPS)w.push_back(p[cnt]);
		if (cnt == cr[0]) {
			if (w.empty() || Distance(w.back(), cp[0]) > EPS)w.push_back(cp[0]);
			if (w.empty() || Distance(w.back(), cp[1]) > EPS)w.push_back(cp[1]);
			cnt = cr[1] + 1;
			cnt %= p.size();
		}
		else if (cnt == cr[1]) {
			if (w.empty() || Distance(w.back(), cp[1]) > EPS)w.push_back(cp[1]);
			if (w.empty() || Distance(w.back(), cp[0]) > EPS)w.push_back(cp[0]);
			cnt = cr[0] + 1;
			cnt %= p.size();
		}
		else {
			cnt++;
			cnt %= p.size();
		}
	} while (cnt != cr[0]);
	cnt = cr[1];
	do {
		if (x.empty() || Distance(x.back(), p[cnt]) > EPS)x.push_back(p[cnt]);
		if (cnt == cr[0]) {
			if (x.empty() || Distance(x.back(), cp[0]) > EPS)x.push_back(cp[0]);
			if (x.empty() || Distance(x.back(), cp[1]) > EPS)x.push_back(cp[1]);
			cnt = cr[1] + 1;
			cnt %= p.size();
		}
		else if (cnt == cr[1]) {
			if (x.empty() || Distance(x.back(), cp[1]) > EPS)x.push_back(cp[1]);
			if (x.empty() || Distance(x.back(), cp[0]) > EPS)x.push_back(cp[0]);
			cnt = cr[0] + 1;
			cnt %= p.size();
		}
		else {
			cnt++;
			cnt %= p.size();
		}
	} while (cnt != cr[1]);
	vector<vector<Point>>ret;
	ret.push_back(w);
	ret.push_back(x);
	return ret;
}

struct Circle {
	long double x, y, r;
	void Input() {
		cin >> x >> y >> r;
	}
	bool operator==(const Circle&c)const {
		return x == c.x&&y == c.y&&r == c.r;
	}
};

vector<Point>CircleCross(Circle a, Circle b) {
	vector<Point>ret;
	Point ap(a.x, a.y);
	Point bp(b.x, b.y);
	Point dp = bp - ap;
	auto dis = Distance(ap, bp);
	if (a == b)return ret;
	if (a.r + b.r < Distance(ap, bp))return ret;
	if (abs(a.r + b.r - dis) <= EPS) {
		ret.push_back(ap + dp * (a.r / (a.r + b.r)));
		return ret;
	}
	if (abs(abs(a.r - b.r) - dis) <= EPS) {
		ret.push_back(ap + dp * (a.r / (a.r - b.r)));
	}
	long double ad;
	ad = (a.r*a.r - b.r*b.r + dis * dis) / 2 / dis;
	Point cp = ap + dp * (ad / dis);
	long double amari = sqrt(a.r*a.r - ad * ad);
	ret.push_back(cp + Point(-dp.y, dp.x)*(amari / dis));
	ret.push_back(cp - Point(-dp.y, dp.x)*(amari / dis));
	return ret;
}

vector<pair<Point, Point>>Common_Tangent(Circle a, Circle b, long double inf) {
	long double pi = acos(-1);
	Point ap = Point(a.x, a.y);
	Point bp = Point(b.x, b.y);
	Point dp = bp - ap;
	vector<pair<Point, Point>>ret;
	long double rad = atan2(dp.y, dp.x);
	long double d = hypot(dp.y, dp.x);
	if (a.r + b.r <= d) {
		long double newrad = asin((a.r + b.r) / d);
		{
			long double fd = hypot(inf, a.r);
			long double lrad = atan2(a.r, -inf);
			long double rrad = atan2(a.r, inf);
			pair<Point, Point>l = { Point(fd*cos(lrad + rad - newrad),fd*sin(lrad + rad - newrad)),Point(fd*cos(rrad + rad - newrad),fd*sin(rrad + rad - newrad)) };
			ret.push_back({ l.first + ap,l.second + ap });
		}
		newrad *= -1;
		{
			long double fd = hypot(inf, -a.r);
			long double lrad = atan2(-a.r, -inf);
			long double rrad = atan2(-a.r, inf);
			pair<Point, Point>l = { Point(fd*cos(lrad + rad - newrad),fd*sin(lrad + rad - newrad)),Point(fd*cos(rrad + rad - newrad),fd*sin(rrad + rad - newrad)) };
			ret.push_back({ l.first + ap,l.second + ap });
		}
	}
	if (abs(a.r - b.r) <= d) {
		long double newrad = asin(abs(a.r - b.r) / d);
		{
			long double fd = hypot(inf, a.r);
			long double lrad = atan2(a.r, -inf);
			long double rrad = atan2(a.r, inf);
			pair<Point, Point>l = { Point(fd*cos(lrad + rad - newrad),fd*sin(lrad + rad - newrad)),Point(fd*cos(rrad + rad - newrad),fd*sin(rrad + rad - newrad)) };
			ret.push_back({ l.first + ap,l.second + ap });
		}
		newrad *= -1;
		{
			long double fd = hypot(inf, -a.r);
			long double lrad = atan2(-a.r, -inf);
			long double rrad = atan2(-a.r, inf);
			pair<Point, Point>l = { Point(fd*cos(lrad + rad - newrad),fd*sin(lrad + rad - newrad)),Point(fd*cos(rrad + rad - newrad),fd*sin(rrad + rad - newrad)) };
			ret.push_back({ l.first + ap,l.second + ap });
		}
	}
	return ret;
}

struct Convex_hull {
	vector<Point>node;
	vector<Point>ret;
	bool line;
	Convex_hull(bool l) {
		line = l;
	}
	void Add_node(Point n) {
		node.push_back(n);
	}
	vector<Point>solve() {
		sort(node.begin(), node.end());
		int index = 0;
		int num = node.size();
		ret.resize(num * 2);
		for (int i = 0; i < num; i++) {
			if (line) {
				while (index > 1 && (ret[index - 1] - ret[index - 2]).det(node[i] - ret[index - 1]) < -EPS) {
					index--;
				}
			}
			else {
				while (index > 1 && (ret[index - 1] - ret[index - 2]).det(node[i] - ret[index - 1]) < EPS) {
					index--;
				}
			}
			ret[index++] = node[i];
		}
		int box = index;
		for (int i = num - 2; i >= 0; i--) {
			if (line) {
				while (index > box && (ret[index - 1] - ret[index - 2]).det(node[i] - ret[index - 1]) < -EPS) {
					index--;
				}
			}
			else {
				while (index > box && (ret[index - 1] - ret[index - 2]).det(node[i] - ret[index - 1]) < EPS) {
					index--;
				}
			}
			ret[index++] = node[i];
		}
		ret.resize(index - 1);
		return ret;
	}
};

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

	while (cin >> N, N) {
		vector<Point>p(N);
		for (int i = 0; i < N; i++) {
			cin >> p[i].x >> p[i].y;
			p[i].x += 2000;
			p[i].y += 2000;
		}
		int ans = 0;
		for (int i = 0; i < 4000; i++) {
			vector<pair<long double, long double>>vp;
			auto ab = Point(EPS+i, -1);
			auto at = Point(EPS+i, 4001);
			auto bb = Point(-EPS+i + 1, -1);
			auto bt = Point(-EPS+i + 1, 4001);
			for (int j = 0; j < N; j++) {
				int nx = (j + 1) % N;
				if (p[j].x == p[nx].x)continue;
				if (LineCross(ab, at, p[j], p[nx]) && LineCross(bb, bt, p[j], p[nx])) {
					vp.push_back({ LineCross(Line(ab,at),Line(p[j],p[nx])).y,LineCross(Line(bb,bt),Line(p[j],p[nx])).y });
				}
			}
			sort(vp.begin(), vp.end());
			if (vp.size()) {
				vector<int>sum(4002);
				for (int j = 1; j < vp.size(); j += 2) {
					sum[(int)(max(vp[j].first, vp[j].second) + 1 - EPS)]--;
					sum[(int)(min(vp[j - 1].first, vp[j - 1].second)) + EPS]++;
				}
				for (int i = 1; i < 4000; i++)sum[i] += sum[i - 1];
				for (int i = 0; i < 4000; i++) {
					if (sum[i])ans++;
				}
			}
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 840
memory_kb: 3480
final_rank: 9

code_snippet: #define MOD_TYPE 1

#pragma region Macros

#include <bits/stdc++.h>
using namespace std;

#if 0
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
using Int = boost::multiprecision::cpp_int;
using lld = boost::multiprecision::cpp_dec_float_100;
#endif
#if 1
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#endif
using ll = long long int;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pld = pair<ld, ld>;
template <typename Q_type>
using smaller_queue = priority_queue<Q_type, vector<Q_type>, greater<Q_type>>;

constexpr ll MOD = (MOD_TYPE == 1 ? (ll)(1e9 + 7) : 998244353);
//constexpr ll MOD = ;
constexpr int INF = (int)1e9 + 10;
constexpr ll LINF = (ll)4e18;
constexpr double PI = acos(-1.0);
constexpr double EPS = 1e-9;
constexpr int Dx[] = {0, 0, -1, 1, -1, 1, -1, 1, 0};
constexpr int Dy[] = {1, -1, 0, 0, -1, -1, 1, 1, 0};

#define REP(i, m, n) for (ll i = m; i < (ll)(n); ++i)
#define rep(i, n) REP(i, 0, n)
#define REPI(i, m, n) for (int i = m; i < (int)(n); ++i)
#define repi(i, n) REPI(i, 0, n)
#define MP make_pair
#define MT make_tuple
#define YES(n) cout << ((n) ? "YES" : "NO") << "\n"
#define Yes(n) cout << ((n) ? "Yes" : "No") << "\n"
#define possible(n) cout << ((n) ? "possible" : "impossible") << "\n"
#define Possible(n) cout << ((n) ? "Possible" : "Impossible") << "\n"
#define Yay(n) cout << ((n) ? "Yay!" : ":(") << "\n"
#define all(v) v.begin(), v.end()
#define NP(v) next_permutation(all(v))
#define dbg(x) cerr << #x << ":" << x << "\n";

struct io_init
{
  io_init()
  {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(30) << setiosflags(ios::fixed);
  };
} io_init;
template <typename T>
inline bool chmin(T &a, T b)
{
  if (a > b)
  {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
inline bool chmax(T &a, T b)
{
  if (a < b)
  {
    a = b;
    return true;
  }
  return false;
}
inline ll CEIL(ll a, ll b)
{
  return (a + b - 1) / b;
}
template <typename A, size_t N, typename T>
inline void Fill(A (&array)[N], const T &val)
{
  fill((T *)array, (T *)(array + N), val);
}
template <typename T, typename U>
constexpr istream &operator>>(istream &is, pair<T, U> &p) noexcept
{
  is >> p.first >> p.second;
  return is;
}
template <typename T, typename U>
constexpr ostream &operator<<(ostream &os, pair<T, U> &p) noexcept
{
  os << p.first << " " << p.second;
  return os;
}
#pragma endregion

using Point = pair<double, double>;
using Segment = pair<Point, Point>;

bool intersect(Segment &s, int x)
{
  auto [p, q] = s;
  auto [x1, y1] = p;
  auto [x2, y2] = q;
  return x1 <= x and x + 1 <= x2;
}

pair<double, double> cut(Segment &s, int x)
{
  auto [p, q] = s;
  auto [x1, y1] = p;
  auto [x2, y2] = q;
  double r1 = (y1 * (x2 - x) + y2 * (x - x1)) / (x2 - x1);
  double r2 = (y1 * (x2 - (x + 1)) + y2 * ((x + 1) - x1)) / (x2 - x1);
  if (r1 > r2)
    swap(r1, r2);
  return {r1, r2};
}

void solve()
{
  int n;
  cin >> n;
  if (!n)
    exit(0);
  vector<Point> p(n);
  rep(i, n) cin >> p[i];
  vector<Segment> S(n);
  rep(i, n)
  {
    S[i] = {p[i], p[(i + 1) % n]};
    if (S[i].first > S[i].second)
      swap(S[i].first, S[i].second);
  }
  int ans = 0;
  for (int x = -2005; x <= 2005; x++)
  {
    vector<pair<double, double>> v;
    rep(i, n)
    {
      if (intersect(S[i], x))
        v.push_back(cut(S[i], x));
    }
    if (v.empty())
      continue;
    sort(all(v));
    int D = -3000;
    for (int i = 0; i + 1 < v.size(); i += 2)
    {
      int L = floor(v[i].first), R = ceil(v[i + 1].second);
      chmax(L, D);
      ans += R - L;
      D = R;
    }
  }
  cout << ans << "\n";
}

int main()
{
  while (1)
    solve();
}
accuracy: 1
time_ms: 40
memory_kb: 3456
final_rank: 4