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

#include <cassert>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
using ll = int64_t;

// For row query R: find first column queried so far. That was before any higher
// row queries. Sorting by low/high and by time.
//
// Find earliest row query < R = ER
// Find first column query that occurred earlier than ER

// given points (x,y)
// Support queries: give me smallest y s.t. exists point (x,y) with x<X
// store them sorted by X descending by Y.
// Query: lookup first thing in map <X. Return corresponding y.
//
// Add: If thing to my left is smaller, delete me.
// While thing to my right is bigger, delete it.
struct Query {
  Query(ll n_) : n(n_) {}
  void add(ll x, ll y) {
    assert(M.count(x) == 0);
    if (M.size() > 0) {
      auto it = M.lower_bound(x);
      if (it != M.begin()) {
        it--;
        if (it->second < y) {
          return;
        } // I am worse
        it++;
      }
      while (it != M.end() && it->second > y) {
        it = M.erase(it);
      }
    }
    M.insert({x, y});
  }
  ll query(ll X) {
    auto it = M.lower_bound(X);
    if (it == M.begin()) {
      return n;
    } else {
      it--;
      return it->second;
    }
  }
  map<ll, ll> M;
  ll n;
};

struct Slow {
  Slow(ll n) {
    ans = (n - 2) * (n - 2);
    G = vector<vector<int>>(n - 2, vector<int>(n - 2, true));
  }
  void query(ll typ, ll idx) {
    idx -= 2;
    assert(0 <= idx && idx < G.size());
    if (typ == 1) { // col
      for (ll r = 0; r < G.size(); r++) {
        if (G[r][idx]) {
          G[r][idx] = false;
          ans--;
        } else {
          break;
        }
      }
    } else {
      for (ll c = 0; c < G.size(); c++) {
        if (G[idx][c]) {
          G[idx][c] = false;
          ans--;
        } else {
          break;
        }
      }
    }
  }
  vector<vector<int>> G;
  ll ans;
};

int main() {
  ll n, q;
  cin >> n >> q;
  ll ans = (n - 2) * (n - 2);
  // Slow slow(n);
  Query EC(5 * n); // pos -> earliest column < pos
  Query FC(n);     // time -> first column earlier than time
  Query ER(5 * n);
  Query FR(n);
  /*EC.add(n, 0);
  FC.add(0, n);
  ER.add(n, 0);
  FR.add(0, n);*/
  for (ll i = 1; i <= q; i++) {
    ll typ, pos;
    cin >> typ >> pos;
    ll removed = 0;
    if (typ == 1) { // col
      ll ec = EC.query(pos);
      ll fr = FR.query(ec);
      removed = fr - 2;
      EC.add(pos, i);
      FC.add(i, pos);
    } else {
      ll er = ER.query(pos);
      ll fc = FC.query(er);
      // cerr << "pos=" << pos << " er=" << er << " fc=" << fc << endl;
      removed = fc - 2;
      ER.add(pos, i);
      FR.add(i, pos);
    }
    ans -= removed;
    // slow.query(typ, pos);
    // cerr << "i=" << i << " typ=" << typ << " pos=" << pos << " removed=" <<
    // removed << " ans=" << ans << " slow.ans=" << slow.ans << endl;
    // assert(slow.ans == ans);
  }
  cout << ans << endl;
}


Error: 0

Fixed submission:

#include <cassert>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
using ll = int64_t;

// For row query R: find first column queried so far. That was before any higher
// row queries. Sorting by low/high and by time.
//
// Find earliest row query < R = ER
// Find first column query that occurred earlier than ER

// given points (x,y)
// Support queries: give me smallest y s.t. exists point (x,y) with x<X
// store them sorted by X descending by Y.
// Query: lookup first thing in map <X. Return corresponding y.
//
// Add: If thing to my left is smaller, delete me.
// While thing to my right is bigger, delete it.
struct Query {
  Query(ll n_) : n(n_) {}
  void add(ll x, ll y) {
    assert(M.count(x) == 0);
    if (M.size() > 0) {
      auto it = M.lower_bound(x);
      if (it != M.begin()) {
        it--;
        if (it->second < y) {
          return;
        } // I am worse
        it++;
      }
      while (it != M.end() && it->second > y) {
        it = M.erase(it);
      }
    }
    M.insert({x, y});
  }
  ll query(ll X) {
    auto it = M.lower_bound(X);
    if (it == M.begin()) {
      return n;
    } else {
      it--;
      return it->second;
    }
  }
  map<ll, ll> M;
  ll n;
};

struct Slow {
  Slow(ll n) {
    ans = (n - 2) * (n - 2);
    G = vector<vector<int>>(n - 2, vector<int>(n - 2, true));
  }
  void query(ll typ, ll idx) {
    idx -= 2;
    assert(0 <= idx && idx < G.size());
    if (typ == 1) { // col
      for (ll r = 0; r < G.size(); r++) {
        if (G[r][idx]) {
          G[r][idx] = false;
          ans--;
        } else {
          break;
        }
      }
    } else {
      for (ll c = 0; c < G.size(); c++) {
        if (G[idx][c]) {
          G[idx][c] = false;
          ans--;
        } else {
          break;
        }
      }
    }
  }
  vector<vector<int>> G;
  ll ans;
};

int main() {
  ll n, q;
  cin >> n >> q;
  ll ans = (n - 2) * (n - 2);
  Slow slow(n);
  Query EC(5 * n); // pos -> earliest column < pos
  Query FC(n);     // time -> first column earlier than time
  Query ER(5 * n);
  Query FR(n);
  /*EC.add(n, 0);
  FC.add(0, n);
  ER.add(n, 0);
  FR.add(0, n);*/
  for (ll i = 1; i <= q; i++) {
    ll typ, pos;
    cin >> typ >> pos;
    ll removed = 0;
    if (typ == 1) { // col
      ll ec = EC.query(pos);
      ll fr = FR.query(ec);
      removed = fr - 2;
      EC.add(pos, i);
      FC.add(i, pos);
    } else {
      ll er = ER.query(pos);
      ll fc = FC.query(er);
      // cerr << "pos=" << pos << " er=" << er << " fc=" << fc << endl;
      removed = fc - 2;
      ER.add(pos, i);
      FR.add(i, pos);
    }
    ans -= removed;
    slow.query(typ, pos);
    // cerr << "i=" << i << " typ=" << typ << " pos=" << pos << " removed=" <<
    // removed << " ans=" << ans << " slow.ans=" << slow.ans << endl;
    assert(slow.ans == ans);
  }
  cout << ans << endl;
}