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



#include <algorithm>
#include <chrono>
#include <fstream>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#define forr(i, start, count) for (int i = (start); i < (start) + (count); ++i)
#define set_map_includes(set, elt) (set.find((elt)) != set.end())
#define readint(i)                                                             \\
  int i;                                                                       \\
  cin >> i
#define readll(i)                                                              \\
  ll i;                                                                        \\
  cin >> i
#define readdouble(i)                                                          \\
  double i;                                                                    \\
  cin >> i
#define readstring(s)                                                          \\
  string s;                                                                    \\
  cin >> s

typedef long long ll;

using namespace std;

template <class T> class depth_first_search_iterator {
public:
  stack<pair<T, T>> todo;
  function<bool(T)> notvisited;
  function<void(T)> mark_visited;
  function<set<T>(T)> neighbors;

  depth_first_search_iterator() {}

  depth_first_search_iterator(T start, function<bool(T)> notv,
                              function<void(T)> mark_v,
                              function<set<T>(T)> neigh)
      : notvisited(notv), mark_visited(mark_v), neighbors(neigh), end_(false),
        current(start), prev(start) {
    todo.push(make_pair(start, start));
    operator++();
  }

  void operator++() {
    end_ = true;
    while (!todo.empty()) {
      current = todo.top().first;
      prev = todo.top().second;
      todo.pop();
      if (notvisited(current)) {
        mark_visited(current);
        for (const T x : neighbors(current)) {
          todo.push(make_pair(x, current));
        }
        end_ = false;
        break;
      }
    }
  }

  T operator*() { return current; }

  T previous() { return prev; }

  bool end() { return end_; }

private:
  T current; // contains current node
  T prev;    // contains previous node
  bool end_;
};

int main() {
  cout.precision(17);
  ll modd = 1000 * 1000 * 1000 + 7;
  mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  uniform_int_distribution<int> rand_gen(
      0, modd); // rand_gen(rng) gets the rand no
  ll infinit = 10000000000000000;

  //    readint(test_cases);
  int test_cases = 1;
  forr(t, 1, test_cases) {
    readint(n);
    readint(m);
    map<ll, int> xcoord, ycoord;
    xcoord[0] = 0;
    ycoord[0] = 0;
    map<ll, vector<pair<ll, ll>>> hor_lines, vert_lines;
    forr(i, 0, n) {
      readll(a);
      readll(b);
      readll(c);
      xcoord[a] = 0;
      xcoord[b] = 0;
      ycoord[c] = 0;
      hor_lines[c].push_back(make_pair(a, b));
    }
    forr(i, 0, m) {
      readll(d);
      readll(e);
      readll(f);
      xcoord[d] = 0;
      ycoord[e] = 0;
      ycoord[f] = 0;
      vert_lines[d].push_back(make_pair(e, f));
    }
    vector<ll> dict_x, dict_y;
    for (auto p : xcoord) {
      dict_x.push_back(p.first);
    }
    for (auto p : ycoord) {
      dict_y.push_back(p.first);
    }
    forr(i, 0, dict_x.size()) { xcoord[dict_x[i]] = i; }
    forr(i, 0, dict_y.size()) { ycoord[dict_y[i]] = i; }

    vector<vector<bool>> visited(dict_x.size(),
                                 vector<bool>(dict_y.size(), false));
    depth_first_search_iterator<pair<int, int>> bfs(
        make_pair(xcoord[0], ycoord[0]),
        [&visited, &dict_x, &dict_y](pair<int, int> x) {
          if ((x.first >= 0) && (x.first < dict_x.size()) && (x.second >= 0) &&
              (x.second < dict_y.size())) {
            return (!visited[x.first][x.second]);
          } else {
            return true;
          }
        },
        [&visited, &dict_y, &dict_x](pair<int, int> x) {
          if ((x.first >= 0) && (x.first < dict_x.size()) && (x.second >= 0) &&
              (x.second < dict_y.size())) {
            visited[x.first][x.second] = true;
          }
        },
        [&hor_lines, &vert_lines, &dict_x, &dict_y](pair<int, int> point) {
          set<pair<int, int>> ret;
          // left
          bool can_go = true;
          if ((point.first >= 0) && (point.first < dict_x.size()) &&
              (point.second >= 0) && (point.second < dict_y.size())) {
            for (auto seg : vert_lines[dict_x[point.first]]) {
              if ((seg.first <= dict_y[point.second]) &&
                  (seg.second > dict_y[point.second])) {
                can_go = false;
                break;
              }
            }
          }
          if (can_go) {
            ret.insert(make_pair(point.first - 1, point.second));
          }
          // down
          can_go = true;
          if ((point.first >= 0) && (point.first < dict_x.size()) &&
              (point.second >= 0) && (point.second < dict_y.size())) {
            for (auto seg : hor_lines[dict_y[point.second]]) {
              if ((seg.first <= dict_x[point.first]) &&
                  (seg.second > dict_x[point.first])) {
                can_go = false;
                break;
              }
            }
          }
          if (can_go) {
            ret.insert(make_pair(point.first, point.second - 1));
          }
          // right
          can_go = true;
          if ((point.first + 1 >= 0) && (point.first + 1 < dict_x.size()) &&
              (point.second >= 0) && (point.second < dict_y.size())) {
            for (auto seg : vert_lines[dict_x[point.first + 1]]) {
              if ((seg.first <= dict_y[point.second]) &&
                  (seg.second > dict_y[point.second])) {
                can_go = false;
                break;
              }
            }
          }
          if (can_go) {
            ret.insert(make_pair(point.first + 1, point.second));
          }
          // up
          can_go = true;
          if ((point.first >= 0) && (point.first < dict_x.size()) &&
              (point.second + 1 >= 0) && (point.second + 1 < dict_y.size())) {
            for (auto seg : hor_lines[dict_y[point.second + 1]]) {
              if ((seg.first <= dict_x[point.first]) &&
                  (seg.second > dict_x[point.first])) {
                can_go = false;
                break;
              }
            }
          }
          if (can_go) {
            ret.insert(make_pair(point.first, point.second + 1));
          }

          return ret;
        });

    ll ret = 0;
    bool infin = false;
    while (!bfs.end()) {
      if ((*bfs).first < 0) {
        infin = true;
        break;
      }
      if ((*bfs).second < 0) {
        infin = true;
        break;
      }
      if ((*bfs).first + 1 >= dict_x.size()) {
        infin = true;
        break;
      }
      if ((*bfs).second + 1 >= dict_y.size()) {
        infin = true;
        break;
      }
      ret += (dict_x[(*bfs).first + 1] - dict_x[(*bfs).first]) *
             (dict_y[(*bfs).second + 1] - dict_y[(*bfs).second]);
      ++bfs;
    }

    if (infin) {
      cout << "INF" << endl;
    } else {
      cout << ret << endl;
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <chrono>
#include <fstream>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#define forr(i, start, count) for (int i = (start); i < (start) + (count); ++i)
#define set_map_includes(set, elt) (set.find((elt)) != set.end())
#define readint(i)                                                             \\
  int i;                                                                       \\
  cin >> i
#define readll(i)                                                              \\
  ll i;                                                                        \\
  cin >> i
#define readdouble(i)                                                          \\
  double i;                                                                    \\
  cin >> i
#define readstring(s)                                                          \\
  string s;                                                                    \\
  cin >> s

typedef long long ll;

using namespace std;

template <class T> class breadth_first_search_iterator {
public:
  queue<pair<T, T>> todo;
  function<bool(T)> notvisited;
  function<void(T)> mark_visited;
  function<set<T>(T)> neighbors;

  breadth_first_search_iterator() {}

  breadth_first_search_iterator(T start, function<bool(T)> notv,
                                function<void(T)> mark_v,
                                function<set<T>(T)> neigh)
      : notvisited(notv), mark_visited(mark_v), neighbors(neigh), end_(false),
        current(start), prev(start) {
    todo.push(make_pair(start, start));
    operator++();
  }

  void operator++() {
    end_ = true;
    while (!todo.empty()) {
      current = todo.front().first;
      prev = todo.front().second;
      todo.pop();
      if (notvisited(current)) {
        mark_visited(current);
        for (const T x : neighbors(current)) {
          todo.push(make_pair(x, current));
        }
        end_ = false;
        break;
      }
    }
  }

  T operator*() { return current; }

  T previous() { return prev; }

  bool end() { return end_; }

private:
  T current; // current node
  T prev;    // previous node
  bool end_;
};

int main() {
  cout.precision(17);
  ll modd = 1000 * 1000 * 1000 + 7;
  mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  uniform_int_distribution<int> rand_gen(
      0, modd); // rand_gen(rng) gets the rand no
  ll infinit = 10000000000000000;

  //    readint(test_cases);
  int test_cases = 1;
  forr(t, 1, test_cases) {
    readint(n);
    readint(m);
    map<ll, int> xcoord, ycoord;
    xcoord[0] = 0;
    ycoord[0] = 0;
    map<ll, vector<pair<ll, ll>>> hor_lines, vert_lines;
    forr(i, 0, n) {
      readll(a);
      readll(b);
      readll(c);
      xcoord[a] = 0;
      xcoord[b] = 0;
      ycoord[c] = 0;
      hor_lines[c].push_back(make_pair(a, b));
    }
    forr(i, 0, m) {
      readll(d);
      readll(e);
      readll(f);
      xcoord[d] = 0;
      ycoord[e] = 0;
      ycoord[f] = 0;
      vert_lines[d].push_back(make_pair(e, f));
    }
    vector<ll> dict_x, dict_y;
    for (auto p : xcoord) {
      dict_x.push_back(p.first);
    }
    for (auto p : ycoord) {
      dict_y.push_back(p.first);
    }
    forr(i, 0, dict_x.size()) { xcoord[dict_x[i]] = i; }
    forr(i, 0, dict_y.size()) { ycoord[dict_y[i]] = i; }

    vector<vector<bool>> can_go_left(xcoord.size(),
                                     vector<bool>(ycoord.size()));
    forr(i, 0, xcoord.size()) {
      forr(j, 0, ycoord.size()) {
        pair<int, int> point(i, j);
        bool can_go = true;
        if ((point.first >= 0) && (point.first < dict_x.size()) &&
            (point.second >= 0) && (point.second < dict_y.size())) {
          for (auto seg : vert_lines[dict_x[point.first]]) {
            if ((seg.first <= dict_y[point.second]) &&
                (seg.second > dict_y[point.second])) {
              can_go = false;
              break;
            }
          }
        }
        can_go_left[i][j] = can_go;
      }
    }
    vector<vector<bool>> can_go_down(xcoord.size(),
                                     vector<bool>(ycoord.size()));
    forr(i, 0, xcoord.size()) {
      forr(j, 0, ycoord.size()) {
        pair<int, int> point(i, j);
        bool can_go = true;
        if ((point.first >= 0) && (point.first < dict_x.size()) &&
            (point.second >= 0) && (point.second < dict_y.size())) {
          for (auto seg : hor_lines[dict_y[point.second]]) {
            if ((seg.first <= dict_x[point.first]) &&
                (seg.second > dict_x[point.first])) {
              can_go = false;
              break;
            }
          }
        }
        can_go_down[i][j] = can_go;
      }
    }

    set<pair<int, int>> visited;
    breadth_first_search_iterator<pair<int, int>> bfs(
        make_pair(xcoord[0], ycoord[0]),
        [&visited](pair<int, int> x) {
          return (!set_map_includes(visited, x));
        },
        [&visited](pair<int, int> x) { visited.insert(x); },
        [&can_go_left, &can_go_down, &dict_x, &dict_y](pair<int, int> point) {
          set<pair<int, int>> ret;
          // left
          bool can_go = true;
          if ((point.first >= 0) && (point.first < dict_x.size()) &&
              (point.second >= 0) && (point.second < dict_y.size())) {
            can_go = can_go_left[point.first][point.second];
          }
          if (can_go) {
            ret.insert(make_pair(point.first - 1, point.second));
          }
          // down
          can_go = true;
          if ((point.first >= 0) && (point.first < dict_x.size()) &&
              (point.second >= 0) && (point.second < dict_y.size())) {
            can_go = can_go_down[point.first][point.second];
          }
          if (can_go) {
            ret.insert(make_pair(point.first, point.second - 1));
          }
          // right
          can_go = true;
          if ((point.first + 1 >= 0) && (point.first + 1 < dict_x.size()) &&
              (point.second >= 0) && (point.second < dict_y.size())) {
            can_go = can_go_left[point.first + 1][point.second];
          }
          if (can_go) {
            ret.insert(make_pair(point.first + 1, point.second));
          }
          // up
          can_go = true;
          if ((point.first >= 0) && (point.first < dict_x.size()) &&
              (point.second + 1 >= 0) && (point.second + 1 < dict_y.size())) {
            can_go = can_go_down[point.first][point.second + 1];
          }
          if (can_go) {
            ret.insert(make_pair(point.first, point.second + 1));
          }

          return ret;
        });

    ll ret = 0;
    bool infin = false;
    while (!bfs.end()) {
      if ((*bfs).first < 0) {
        infin = true;
        break;
      }
      if ((*bfs).second < 0) {
        infin = true;
        break;
      }
      if ((*bfs).first + 1 >= dict_x.size()) {
        infin = true;
        break;
      }
      if ((*bfs).second + 1 >= dict_y.size()) {
        infin = true;
        break;
      }
      ret += (dict_x[(*bfs).first + 1] - dict_x[(*bfs).first]) *
             (dict_y[(*bfs).second + 1] - dict_y[(*bfs).second]);
      ++bfs;
    }

    if (infin) {
      cout << "INF" << endl;
    } else {
      cout << ret << endl;
    }
  }
  return 0;
}