Problem p00749 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

#define REP(i, a, b) for (int i = a; i < (int)b; i++)
#define rep(i, n) REP(i, 0, n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a)                                                               \\
  { cout << #a << " = " << a << endl; }
template <class T1, class T2> inline bool minimize(T1 &a, T2 b) {
  return b < a && (a = b, 1);
}
template <class T1, class T2> inline bool maximize(T1 &a, T2 b) {
  return a < b && (a = b, 1);
}

typedef long long ll;
int const inf = 1 << 29;

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

int H, W;
int K;
vector<string> G;
int color[66][11];

bool equals(double a, double b) { return abs(a - b) < 1e-10; }

struct Data {
  double y, x;
  int w;
  Data(double y, double x, int w) : y(y), x(x), w(w) {}
};

static auto InvalidData = Data(0, 0, -inf);

bool operator==(const Data &a, const Data &b) {
  return equals(a.y, b.y) && equals(b.x, b.x) && a.w == b.w;
}

void coloring(int y, int x, vector<vector<bool>> &vis) {
  color[y][x] = K;
  rep(k, 4) {
    int ny = y + dy[k], nx = x + dx[k];
    if (!in_range(ny, nx, H, W))
      continue;
    if (G[ny][nx] != G[y][x])
      continue;
    if (vis[ny][nx])
      continue;
    vis[ny][nx] = 1;
    coloring(ny, nx, vis);
  }
}

vector<int> getChildrenColors(int pcnum) {
  vector<int> ret;
  rep(i, H) rep(j, W) {
    if (color[i][j] == -1)
      continue;
    if (!in_range(i + 1, j, H, W))
      continue;
    if (color[i][j] != pcnum && color[i + 1][j] == pcnum)
      ret.push_back(color[i][j]);
  }
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}

Data getBlockData(int cnum) {
  int num = 0;
  double y = 0, x = 0;
  rep(i, H) rep(j, W) {
    if (color[i][j] == cnum) {
      num++;
      y += i + 0.5;
      x += j + 0.5;
    }
  }

  y /= num;
  x /= num;

  //  cout << "block data: " << cnum << endl; printf("%.10f %.10f %d\\n", y, x,
  //  num);
  return Data(y, x, num);
}

pair<int, int> getBlockHeadX(int col) {
  int xL = 1000, xR = -1;
  rep(i, H) rep(j, W) {
    if (color[i][j] != -1 && color[i][j] != col && in_range(i + 1, j, H, W) &&
        color[i + 1][j] == col) {
      minimize(xL, j);
      maximize(xR, j + 1);
    }
  }
  return make_pair(xL, xR);
}

pair<int, int> getBlockBottomOnBlock(int mycol, int pcol) {
  int xL = 1000, xR = -1;
  int top = -1;
  rep(i, H) rep(j, W) {
    if (color[i][j] != -1 && color[i][j] == mycol && in_range(i + 1, j, H, W) &&
        color[i + 1][j] == pcol) {
      if (top > i) {
        top = i;
        xL = j;
        xR = j + 1;
      } else {
        minimize(xL, j);
        maximize(xR, j + 1);
      }
    }
  }
  return make_pair(xL, xR);
}

bool safeY(double cy, int cnum) {
  bool safe = 0;
  rep(i, H) rep(j, W) {
    if (color[i][j] == cnum) {
      safe |= cy < i;
    }
  }
  //  watch(safe)
  return safe;
}

// template<class T> ostream& operator << (ostream& ost, vector<T> const& v) {
// ost << "["; rep(i, v.size()) { if(i) ost << ", "; ost << v[i]; } ost << "]";
// return ost; }

Data rec(int col) {

  auto vc = getChildrenColors(col);
  //  cout << endl; watch(cnum);// cout << vc << endl;
  //  watch(xlxr.first) watch(xlxr.second)

  double y = 0, x = 0;
  int w = 0;
  for (auto u : vc) {
    auto e = rec(u);
    if (e == InvalidData)
      return InvalidData;
    y += e.y * e.w;
    x += e.x * e.w;
    w += e.w;
    auto xlxr = getBlockBottomOnBlock(u, col);
    if (e.x <= xlxr.first || xlxr.second <= e.x)
      return InvalidData;
  }

  if (w > 0) {
    auto xlxr = getBlockHeadX(col);
    double cy = y / w, cx = x / w;
    if (!safeY(cy, col))
      return InvalidData; // topテ」ツ?古ゥツォツ佚」ツ??」ツ?サテ」ツ??」ツ?古、ツクツ?
    if (cx <= xlxr.first || xlxr.second <= cx)
      return InvalidData;
  }

  auto mydata = getBlockData(col);
  y += mydata.y * mydata.w;
  x += mydata.x * mydata.w;
  w += mydata.w;

  y /= w;
  x /= w;

  return Data(y, x, w);
}

bool solve() {
  int bottomc = -1;
  int xl = -1, xr = -1;

  rep(j, W) if (color[H - 1][j] != -1) {
    bottomc = color[H - 1][j];
    xl = j;
    break;
  }

  for (int j = W - 1; j >= 0; j--)
    if (color[H - 1][j] != -1) {
      xr = j + 1;
      break;
    }

  auto d = rec(bottomc);
  if (d == InvalidData)
    return false;

  //  cout << "my sweet angel ayasetan" << endl; watch(xl); watch(xr); cout <<
  //  "d.x = " << d.x << endl;

  return xl < d.x && d.x < xr;
}

int main() {

  while (cin >> W >> H && (W | H)) {
    G.clear();
    G.resize(H);
    rep(i, H) cin >> G[i];
    rep(i, 66) rep(j, 11) color[i][j] = -1;

    K = 0;
    vector<vector<bool>> vis(H, vector<bool>(W));
    rep(i, H) rep(j, W) {
      if (G[i][j] == '.')
        continue;
      if (vis[i][j])
        continue;
      vis[i][j] = 1;
      coloring(i, j, vis);
      K++;
    }

    //    rep(i, H) rep(j, W) {   printf("%c", color[i][j] == -1 ? '.' :
    //    color[i][j] > 9 ? color[i][j] - 10 + 'A' : '0' + color[i][j]);    if(j
    //    == W-1) cout << endl;   }

    cout << (solve() ? "STABLE" : "UNSTABLE") << endl;
  }

  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

#define REP(i, a, b) for (int i = a; i < (int)b; i++)
#define rep(i, n) REP(i, 0, n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a)                                                               \\
  { cout << #a << " = " << a << endl; }
template <class T1, class T2> inline bool minimize(T1 &a, T2 b) {
  return b < a && (a = b, 1);
}
template <class T1, class T2> inline bool maximize(T1 &a, T2 b) {
  return a < b && (a = b, 1);
}

typedef long long ll;
int const inf = 1 << 29;

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

namespace solver {
int H, W;
int K;
vector<string> G;
int color[11][66];

bool equals_(double a, double b) { return abs(a - b) < 1e-10; }

struct Data {
  double y, x;
  int w;
  Data(double y, double x, int w) : y(y), x(x), w(w) {}
};

static auto InvalidData = Data(0, 0, -inf);

bool operator==(const Data &a, const Data &b) {
  return equals_(a.y, b.y) && equals_(b.x, b.x) && a.w == b.w;
}

void coloring(int y, int x, vector<vector<bool>> &vis) {
  color[y][x] = K;
  rep(k, 4) {
    int ny = y + dy[k], nx = x + dx[k];
    if (!in_range(ny, nx, H, W))
      continue;
    if (G[ny][nx] != G[y][x])
      continue;
    if (vis[ny][nx])
      continue;
    vis[ny][nx] = 1;
    coloring(ny, nx, vis);
  }
}

vector<int> getChildrenNum(int pcnum) {
  vector<int> ret;
  rep(i, H) rep(j, W) {
    if (color[i][j] == -1)
      continue;
    if (!in_range(i + 1, j, H, W))
      continue;
    if (color[i][j] != pcnum && color[i + 1][j] == pcnum)
      ret.push_back(color[i][j]);
  }
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}

Data getBlockData(int cnum) {
  int num = 0;
  double y = 0, x = 0;
  rep(i, H) rep(j, W) {
    if (color[i][j] == cnum) {
      num++;
      y += i + 0.5;
      x += j + 0.5;
    }
  }

  y /= num;
  x /= num;

  //  cout << "block data: " << cnum << endl; watch(y); watch(x); watch(num);
  return Data(y, x, num);
}

pair<int, int> getBlockHeadX(int col) {
  int xL = 1000, xR = -1;
  rep(i, H) rep(j, W) {
    if (color[i][j] != -1 && color[i][j] != col && in_range(i + 1, j, H, W) &&
        color[i + 1][j] == col) {
      minimize(xL, j);
      maximize(xR, j + 1);
    }
  }
  //  watch(xL) watch(xR)
  return make_pair(xL, xR);
}

bool safeY(double cy, int cnum) {
  bool safe = 0;
  rep(i, H) rep(j, W) {
    if (color[i][j] == cnum) {
      safe |= cy < i;
    }
  }
  //  watch(safe)
  return safe;
}

// template<class T> ostream& operator << (ostream& ost, vector<T> const& v) {
// ost << "["; rep(i, v.size()) { if(i) ost << ", "; ost << v[i]; } ost << "]";
// return ost; }

Data rec(int cnum) {

  auto vc = getChildrenNum(cnum);
  //  watch(cnum); cout << vc << endl;

  double y = 0, x = 0;
  int w = 0;
  for (auto u : vc) {
    auto e = rec(u);
    if (e == InvalidData)
      return InvalidData;
    y += e.y * e.w;
    x += e.x * e.w;
    w += e.w;
  }

  if (w > 0) {
    double cy = y / w, cx = x / w;
    auto xlxr = getBlockHeadX(cnum);
    if (!safeY(cy, cnum))
      return InvalidData; // topテ」ツ?古ゥツォツ佚」ツ??」ツ?サテ」ツ??」ツ?古、ツクツ?
    if (cx <= xlxr.first || xlxr.second <= cx)
      return InvalidData;
  }

  auto mydata = getBlockData(cnum);
  y += mydata.y * mydata.w;
  x += mydata.x * mydata.w;
  w += mydata.w;

  y /= w;
  x /= w;

  return Data(y, x, w);
}

bool solve() {
  int bottomc = -1;
  int xl = -1, xr = -1;
  rep(j, W) {
    if (color[H - 1][j] != -1) {
      bottomc = color[H - 1][j];
      xl = j;
      break;
    }
  }

  for (int j = W - 1; j >= 0; j--) {
    if (color[H - 1][j] != -1) {
      xr = j + 1;
      break;
    }
  }

  auto d = rec(bottomc);
  if (d == InvalidData)
    return false;

  //  cout << "my sweet angel ayasetan" << endl; watch(xl); watch(xr); cout <<
  //  "d.x = " << d.x << endl;

  return xl < d.x && d.x < xr;
}

int main() {

  while (cin >> W >> H && (W | H)) {
    G.clear();
    G.resize(H);
    rep(i, H) cin >> G[i];
    rep(i, 11) rep(j, 66) color[i][j] = -1;

    K = 0;
    vector<vector<bool>> vis(H, vector<bool>(W));
    rep(i, H) rep(j, W) {
      if (G[i][j] == '.')
        continue;
      if (vis[i][j])
        continue;
      vis[i][j] = 1;
      coloring(i, j, vis);
      K++;
    }

    //    rep(i, H) rep(j, W) {   printf("%2d", color[i][j]);    if(j == W-1)
    //    cout << endl;   }

    cout << (solve() ? "STABLE" : "UNSTABLE") << endl;
  }

  return 0;
}
} // namespace solver

int main() { return solver::main(); }