Problem p00821 (C++) — buggy submission, verdict: Time Limit Exceeded

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

#define rep(i, n) for (int i = 0; i < (n); i++)
typedef double D;     // 座標値の型。doubleかlong doubleを想定
typedef complex<D> P; // Point
typedef pair<P, P> L; // Line
typedef vector<P> VP;
typedef vector<VP> Vcon;
const D EPS = 1e-9; // 許容誤差。問題によって変える
#define X real()
#define Y imag()
#define LE(n, m) ((n) < (m) + EPS)
#define GE(n, m) ((n) + EPS > (m))
#define EQ(n, m) (abs((n) - (m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
D dot(P a, P b) { return (conj(a) * b).X; }

// 外積　cross(a,b) = |a||b|sinθ
D cross(P a, P b) { return (conj(a) * b).Y; }

// 点の進行方向
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return +1; // counter clockwise
  if (cross(b, c) < -EPS)
    return -1; // clockwise
  if (dot(b, c) < -EPS)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line or a==b
  return 0;    // a--c--b on line or a==c or b==c
}

bool isparallel(L a, L b) {
  return cross(a.first - a.second, b.first - b.second) == 0.0;
}

/* 交差判定　直線・線分は縮退してはならない。接する場合は交差するとみなす。isecはintersectの略
 */

// 直線と点
bool isecLP(P a1, P a2, P b) {
  return abs(ccw(a1, a2, b)) != 1; // return EQ(cross(a2-a1, b-a1), 0); と等価
}

// 直線と直線
bool isecLL(P a1, P a2, P b1, P b2) {
  return !isecLP(a2 - a1, b2 - b1, 0) || isecLP(a1, b1, b2);
}

// 直線と線分
bool isecLS(P a1, P a2, P b1, P b2) {
  return cross(a2 - a1, b1 - a1) * cross(a2 - a1, b2 - a1) < EPS;
}

// 線分と線分
bool isecSS(P a1, P a2, P b1, P b2) {
  return ccw(a1, a2, b1) * ccw(a1, a2, b2) <= 0 &&
         ccw(b1, b2, a1) * ccw(b1, b2, a2) <= 0;
}

// 線分と点
bool isecSP(P a1, P a2, P b) {
  // return !ccw(a1, a2, b);
  return abs(a1 - b) + abs(a2 - b) - abs(a2 - a1) < EPS; // Perfective
}

/* 距離　各直線・線分は縮退してはならない */

// 点pの直線aへの射影点を返す
P proj(P a1, P a2, P p) {
  return a1 + dot(a2 - a1, p - a1) / norm(a2 - a1) * (a2 - a1);
}

// 点pの直線aへの反射点を返す
P reflection(P a1, P a2, P p) { return 2.0 * proj(a1, a2, p) - p; }

D distLP(P a1, P a2, P p) { return abs(proj(a1, a2, p) - p); }

D distLL(P a1, P a2, P b1, P b2) {
  return isecLL(a1, a2, b1, b2) ? 0 : distLP(a1, a2, b1);
}

D distLS(P a1, P a2, P b1, P b2) {
  return isecLS(a1, a2, b1, b2) ? 0
                                : min(distLP(a1, a2, b1), distLP(a1, a2, b2));
}

D distSP(P a1, P a2, P p) {
  P r = proj(a1, a2, p);
  if (isecSP(a1, a2, r))
    return abs(r - p);
  return min(abs(a1 - p), abs(a2 - p));
}

D distSS(P a1, P a2, P b1, P b2) {
  if (isecSS(a1, a2, b1, b2))
    return 0;
  return min(min(distSP(a1, a2, b1), distSP(a1, a2, b2)),
             min(distSP(b1, b2, a1), distSP(b1, b2, a2)));
}

// 2直線の交点
P crosspointLL(P a1, P a2, P b1, P b2) {
  D d1 = cross(b2 - b1, b1 - a1);
  D d2 = cross(b2 - b1, a2 - a1);
  if (EQ(d1, 0) && EQ(d2, 0))
    return a1; // same line
  if (EQ(d2, 0))
    throw "kouten ga nai"; // 交点がない
  return a1 + d1 / d2 * (a2 - a1);
}

typedef pair<D, D> PP;
#define fi first
#define se second

const D eps = 1e-4;

signed main() {
  int n;
  while (cin >> n, n) {
    int ans = 0;
    VP v;
    rep(i, n) {
      D x, y;
      cin >> x >> y;
      v.push_back(P(x, y));
    }
    for (int y = -2000; y <= 2000; y++) {
      vector<PP> x;
      P l = P(-1, y + eps), r = P(1, y + eps);
      P L = P(-1, 1 + y - eps), R = P(1, 1 + y - eps);
      rep(i, n) {
        if (distLS(l, r, v[i], v[(i + 1) % n]) == 0) { // cout<<y<<endl;
          P p = crosspointLL(l, r, v[i], v[(i + 1) % n]);
          P pp = crosspointLL(L, R, v[i], v[(i + 1) % n]);
          D a = p.X;
          D b = pp.X;
          if (a > b)
            swap(a, b);
          x.push_back(PP(a, b));
        }
      }
      sort(x.begin(), x.end());
      set<int> st;
      rep(i, x.size()) {
        if (i % 2 == 0)
          x[i].fi = floor(x[i].fi);
        else
          x[i].se = ceil(x[i].se);
      }
      rep(i, x.size() / 2) {
        int l = x[i * 2].fi, r = x[i * 2 + 1].se;
        for (int i = l; i < r; i++) {
          st.insert(i);
        }
      }
      // if(st.size())cout<<st.size()<<endl;
      ans += st.size();
    }
    cout << ans << endl;
  }
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
typedef double D;     // 座標値の型。doubleかlong doubleを想定
typedef complex<D> P; // Point
typedef pair<P, P> L; // Line
typedef vector<P> VP;
typedef vector<VP> Vcon;
const D EPS = 1e-7; // 許容誤差。問題によって変える
#define X real()
#define Y imag()
#define LE(n, m) ((n) < (m) + EPS)
#define GE(n, m) ((n) + EPS > (m))
#define EQ(n, m) (abs((n) - (m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
D dot(P a, P b) { return (conj(a) * b).X; }

// 外積　cross(a,b) = |a||b|sinθ
D cross(P a, P b) { return (conj(a) * b).Y; }

// 点の進行方向
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return +1; // counter clockwise
  if (cross(b, c) < -EPS)
    return -1; // clockwise
  if (dot(b, c) < -EPS)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line or a==b
  return 0;    // a--c--b on line or a==c or b==c
}

bool isparallel(L a, L b) {
  return cross(a.first - a.second, b.first - b.second) == 0.0;
}

/* 交差判定　直線・線分は縮退してはならない。接する場合は交差するとみなす。isecはintersectの略
 */

// 直線と点
bool isecLP(P a1, P a2, P b) {
  return abs(ccw(a1, a2, b)) != 1; // return EQ(cross(a2-a1, b-a1), 0); と等価
}

// 直線と直線
bool isecLL(P a1, P a2, P b1, P b2) {
  return !isecLP(a2 - a1, b2 - b1, 0) || isecLP(a1, b1, b2);
}

// 直線と線分
bool isecLS(P a1, P a2, P b1, P b2) {
  return cross(a2 - a1, b1 - a1) * cross(a2 - a1, b2 - a1) < EPS;
}

// 線分と線分
bool isecSS(P a1, P a2, P b1, P b2) {
  return ccw(a1, a2, b1) * ccw(a1, a2, b2) <= 0 &&
         ccw(b1, b2, a1) * ccw(b1, b2, a2) <= 0;
}

// 線分と点
bool isecSP(P a1, P a2, P b) {
  // return !ccw(a1, a2, b);
  return abs(a1 - b) + abs(a2 - b) - abs(a2 - a1) < EPS; // Perfective
}

/* 距離　各直線・線分は縮退してはならない */

// 点pの直線aへの射影点を返す
P proj(P a1, P a2, P p) {
  return a1 + dot(a2 - a1, p - a1) / norm(a2 - a1) * (a2 - a1);
}

// 点pの直線aへの反射点を返す
P reflection(P a1, P a2, P p) { return 2.0 * proj(a1, a2, p) - p; }

D distLP(P a1, P a2, P p) { return abs(proj(a1, a2, p) - p); }

D distLL(P a1, P a2, P b1, P b2) {
  return isecLL(a1, a2, b1, b2) ? 0 : distLP(a1, a2, b1);
}

D distLS(P a1, P a2, P b1, P b2) {
  return isecLS(a1, a2, b1, b2) ? 0
                                : min(distLP(a1, a2, b1), distLP(a1, a2, b2));
}

D distSP(P a1, P a2, P p) {
  P r = proj(a1, a2, p);
  if (isecSP(a1, a2, r))
    return abs(r - p);
  return min(abs(a1 - p), abs(a2 - p));
}

D distSS(P a1, P a2, P b1, P b2) {
  if (isecSS(a1, a2, b1, b2))
    return 0;
  return min(min(distSP(a1, a2, b1), distSP(a1, a2, b2)),
             min(distSP(b1, b2, a1), distSP(b1, b2, a2)));
}

// 2直線の交点
P crosspointLL(P a1, P a2, P b1, P b2) {
  D d1 = cross(b2 - b1, b1 - a1);
  D d2 = cross(b2 - b1, a2 - a1);
  if (EQ(d1, 0) && EQ(d2, 0))
    return a1; // same line
  if (EQ(d2, 0))
    throw "kouten ga nai"; // 交点がない
  return a1 + d1 / d2 * (a2 - a1);
}

int n;
vector<L> v;

bool han(double y, double x) {
  int s1 = 0, s2 = 0, s3 = 0, s4 = 0;
  rep(i, n) {
    if (isecSS(v[i].first, v[i].second, P(y, x), P(y + 1, x)) &&
        !isparallel(v[i], L(P(y, x), P(y + 1, x))))
      return 1;
    if (isecSS(v[i].first, v[i].second, P(y, x), P(y, x + 1)) &&
        !isparallel(v[i], L(P(y, x), P(y, x + 1))))
      return 1;
    if (isecSS(v[i].first, v[i].second, P(y + 1, x), P(y + 1, x + 1)) &&
        !isparallel(v[i], L(P(y + 1, x), P(y + 1, x + 1))))
      return 1;
    if (isecSS(v[i].first, v[i].second, P(y, x + 1), P(y + 1, x + 1)) &&
        !isparallel(v[i], L(P(y, x + 1), P(y + 1, x + 1))))
      return 1;
  }
  rep(i, n) {
    if (isecLS(P(y + EPS, x + EPS), P(100002312, 213), v[i].first, v[i].second))
      s1++;
    if (isecLS(P(y + 1 - EPS, x + EPS), P(100002312, 213), v[i].first,
               v[i].second))
      s2++;
    if (isecLS(P(y + EPS, x + 1 - EPS), P(100002312, 213), v[i].first,
               v[i].second))
      s3++;
    if (isecLS(P(y + 1 - EPS, x + 1 - EPS), P(100002312, 213), v[i].first,
               v[i].second))
      s4++;
  }
  if ((s1 % 2) || (s2 % 2) || (s3 % 2) || (s4 % 2))
    return 1;
  return 0;
}

signed main() {
  while (cin >> n, n) {
    int ans = 0;
    v.clear();
    vector<P> vv;
    rep(i, n) {
      D x, y;
      cin >> x >> y;
      vv.push_back(P(x, y));
    }
    rep(i, n) v.push_back(L(vv[i], vv[(i + 1) % n]));
    for (int x = -1999; x <= 1999; x += 64) {
      for (int y = -1999; y <= 1999; y += 64) {
        int flag = 0;
        for (int i = 0; i < 64; i++)
          if (han(y, x + i))
            flag++;
        for (int i = 0; i < 64; i++)
          if (han(y, x + i))
            flag++;
        for (int i = 0; i < 64; i++)
          if (han(y, x + i))
            flag++;
        for (int i = 0; i < 64; i++)
          if (han(y, x + i))
            flag++;
        if (!flag)
          continue;
        if (flag == 64 * 4)
          ans += 64 * 64;
        else {
          rep(i, 64) {
            rep(j, 64) {
              if (han(y + i, x + j))
                ans++;
            }
          }
        }
      }
    }
    cout << ans << endl;
  }
}