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

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

using ld = long double;
ld EPS = 1e-12;
const int GETA = 2010;
const int MAX = 4200;
int n;

typedef pair<ld, ld> Pdd;
ld X[100], Y[100];

ld f(ld a, ld b, ld y) { return (y - b) / a; }

ld g(int p, int q, int i) {
  if (Y[p] < Y[q])
    swap(p, q);
  double a = Y[p] - i, b = i - Y[q];
  return (b * X[p] + a * X[q]) / (a + b);
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
#ifdef LOCAL
  std::ifstream in("in");
  std::cin.rdbuf(in.rdbuf());
#endif

  while (cin >> n, n) {
    for (int i = 0; i < n; i++) {
      cin >> X[i] >> Y[i];
    }
    int ans = 0;
    for (int y = -2010; y <= 2010; y++) {
      // y??????(y+1)
      vector<Pdd> v;
      for (int i = 0; i < n; i++) {
        int ni = (i + 1) % n;
        if (Y[i] == Y[ni] || y < min(Y[i], Y[ni]) || y + 1 > max(Y[i], Y[ni]))
          continue;
        ld x1 = g(i, ni, y), x2 = g(i, ni, y + 1);
        if (x1 > x2)
          swap(x1, x2);
        v.push_back({x1, x2});
      }
      if (v.size() == 0)
        continue;
      sort(v.begin(), v.end());
      int xr = -5000;
      for (int i = 0; i < v.size(); i += 2) {
        Pdd d1 = v[i], d2 = v[i + 1];
        int l = max(int(floor(d1.first)), xr);
        int r = ceil(d2.second);
        // cout << y << " " << r - l << endl;
        ans += r - l;
        xr = r;
      }
    }
    cout << ans << endl;
  }
}

Error: MLE

Fixed submission:

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

const int GETA = 2010;
const int MAX = 4200;
int n;
bool b[MAX][MAX];
bool NG[MAX][MAX][4];

bool In(int x, int y) { return 0 <= x && x < MAX && 0 <= y && y < MAX; }
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};

struct UnionFind {
  vector<int> par;
  int cnt;
  UnionFind(int size_) : par(size_, -1), cnt(size_) {}
  void unite(int x, int y) {
    if ((x = find(x)) != (y = find(y))) {
      if (par[y] < par[x])
        swap(x, y);
      par[x] += par[y];
      par[y] = x;
      cnt--;
    }
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int find(int x) { return par[x] < 0 ? x : par[x] = find(par[x]); }
  int size(int x) { return -par[find(x)]; }
  int size() { return cnt; }
} uf(MAX *MAX);

struct P {
  int x, y;
} p[100];

int toV(int x, int y) { return y * MAX + x; }

void connect() {
  uf.cnt = uf.par.size();
  for (int i = 0; i < uf.par.size(); i++) {
    uf.par[i] = -1;
  }
  for (int y = 0; y < MAX; y++) {
    for (int x = 0; x < MAX; x++) {
      for (int k = 0; k < 4; k++) {
        if (NG[y][x][k])
          continue;
        int nx = x + dx[k], ny = y + dy[k];
        if (!In(nx, ny))
          continue;
        if (b[y][x] != b[ny][nx])
          continue;
        uf.unite(toV(x, y), toV(nx, ny));
      }
    }
  }
}

void check(P p1, P p2) {
  if (p1.x == p2.x) {
    int x = p1.x;
    int ly = min(p1.y, p2.y), ry = max(p1.y, p2.y);
    // ???0 ???2
    for (int i = ly; i < ry; i++) {
      NG[i][x - 1][0] = NG[i][x][2] = 1;
    }
    return;
  }
  if (p1.y == p2.y) {
    int y = p1.y;
    int lx = min(p1.x, p2.x), rx = max(p1.x, p2.x);
    // ???1 ???3
    for (int i = lx; i < rx; i++) {
      NG[y - 1][i][1] = NG[y][i][3] = 1;
    }
    return;
  }

  if (p1.x > p2.x)
    swap(p1, p2);
  int lx = p1.x, rx = p2.x;
  double a = double(p2.y - p1.y) / (rx - lx);
  double cx = p1.x, cy = p1.y;
  double TX = cx + 1, TY = cy + (a > 0 ? 1 : -1);
  while (true) {
    double t = abs(TY - cy) / abs(a);
    double dx = abs(TX - cx);
    double tx, ty;
    // y?????¶?????????
    if (t < dx) {
      ty = TY;
      tx = cx + t;
      TY += (a > 0 ? 1 : -1);
    }
    // x?????¶?????????
    else {
      tx = TX;
      ty = cy + a * dx;
      TX++;
    }

    int xx = int((cx + tx) / 2), yy = int((cy + ty) / 2);
    b[yy][xx] = 1;
    // cout << xx << " " << yy << endl;
    cx = tx, cy = ty;
    if (abs(cx - TX) < 1e-8)
      TX++;
    if (abs(cy - TY) < 1e-8)
      TY += (a > 0 ? 1 : -1);
    if (abs(cx - rx) < 1e-8)
      break;
  }
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
#ifdef LOCAL
  std::ifstream in("in");
  std::cin.rdbuf(in.rdbuf());
#endif

  while (cin >> n, n) {
    memset(b, 0, sizeof b);
    memset(NG, 0, sizeof NG);

    for (int i = 0; i < n; i++) {
      cin >> p[i].x >> p[i].y;
      p[i].x += GETA, p[i].y += GETA;
    }
    for (int i = 0; i < n; i++) {
      check(p[i], p[(i + 1) % n]);
    }

    connect();
    int ans = 0;
    for (int i = 0; i < MAX; i++) {
      for (int j = 0; j < MAX; j++) {
        if (!uf.same(0, toV(j, i)))
          ans++;
      }
    }
    cout << ans << endl;

    /*	for(int i = 30; i >= 0; i--){
                    for(int j = 0; j < 30; j++){
                            cout << vis[i][j];
                    }
                    cout << endl;
            }*/
  }
}