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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 3000

enum DIR {
  North,
  East,
  South,
  West,
};

struct Info {
  int x, y;
  DIR dir;
};

typedef pair<int, int> Data;
int N;
map<int, int> X_MAP, Y_MAP;
vector<int> Y, X;
Info info[NUM];
set<Data> SET_X[NUM], SET_Y[NUM];

int main() {

  scanf("%d", &N);

  char buf[2];

  for (int i = 0; i < N; i++) {
    scanf("%d %d %s", &info[i].x, &info[i].y, buf);
    X.push_back(info[i].x);
    Y.push_back(info[i].y);
    switch (buf[0]) {
    case '^':
      info[i].dir = North;
      break;
    case '>':
      info[i].dir = East;
      break;
    case 'v':
      info[i].dir = South;
      break;
    case '<':
      info[i].dir = West;
      break;
    }
  }

  sort(X.begin(), X.end());
  sort(Y.begin(), Y.end());

  X.erase(unique(X.begin(), X.end()), X.end());
  Y.erase(unique(Y.begin(), Y.end()), Y.end());

  for (int i = 0; i < X.size(); i++) {
    X_MAP[X[i]] = i;
  }
  for (int i = 0; i < Y.size(); i++) {
    Y_MAP[Y[i]] = i;
  }

  int size_X = (int)X.size(), size_Y = (int)Y.size();

  for (int i = 0; i < N; i++) {
    info[i].y = Y_MAP[info[i].y];
    info[i].x = X_MAP[info[i].x];
  }

  int ans = 0;
  int x, y, next_index;
  DIR dir;
  Data tmp;
  bool FLG;

  for (int start = 0; start < N; start++) {

    for (int i = 0; i < NUM; i++) {
      SET_X[i].clear();
      SET_Y[i].clear();
    }

    int tmp_count = 1;

    for (int i = 0; i < N; i++) {
      if (i == start)
        continue;
      SET_X[info[i].x].insert(Data(info[i].y, i));
      SET_Y[info[i].y].insert(Data(info[i].x, i));
    }

    dir = info[start].dir;
    x = info[start].x;
    y = info[start].y;

    FLG = true;

    set<Data>::iterator it;

    while (true) {

      switch (dir) {
      case North:
        it = SET_X[x].lower_bound(Data(y, 0));
        if (it == SET_X[x].begin()) {
          FLG = false;
        } else {
          it--;
          tmp = *it;
          next_index = tmp.second;
        }
        break;
      case East:
        it = SET_Y[y].lower_bound(Data(x, 0));
        if (it == SET_Y[y].end()) {
          FLG = false;
        } else {
          tmp = *it;
          next_index = tmp.second;
        }
        break;
      case South:
        it = SET_X[x].lower_bound(Data(y, 0));
        if (it == SET_X[x].end()) {
          FLG = false;
        } else {
          tmp = *it;
          next_index = tmp.second;
        }
        break;
      case West:
        it = SET_Y[y].lower_bound(Data(x, 0));
        if (it == SET_Y[y].begin()) {
          FLG = false;
        } else {
          it--;
          tmp = *it;
          next_index = tmp.second;
        }
        break;
      }

      if (!FLG)
        break;

      tmp_count++;
      x = info[next_index].x;
      y = info[next_index].y;
      dir = info[next_index].dir;
      SET_X[x].erase(Data(y, next_index));
      SET_Y[y].erase(Data(x, next_index));
    }
    ans = max(ans, tmp_count);
  }

  printf("%d\\n", ans);

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 3000

enum DIR {
  North,
  East,
  South,
  West,
};

struct Info {
  int x, y;
  DIR dir;
};

struct Data {
  int x_index, y_index;
  DIR dir;
  bool exist, visited;
};

struct State {
  void set(int arg_y, int arg_x, DIR arg_dir) {
    y = arg_y;
    x = arg_x;
    dir = arg_dir;
  }
  int x, y;
  DIR dir;
};

int N;
map<int, int> X_MAP, Y_MAP;
vector<int> Y, X, comp_X[NUM], comp_Y[NUM];
Info info[NUM];
Data data[NUM][NUM]; // 座標圧縮した2次元フィールド

int main() {

  scanf("%d", &N);

  char buf[2];

  for (int i = 0; i < N; i++) {
    scanf("%d %d %s", &info[i].x, &info[i].y, buf);
    X.push_back(info[i].x);
    Y.push_back(info[i].y);
    switch (buf[0]) {
    case '^':
      info[i].dir = North;
      break;
    case '>':
      info[i].dir = East;
      break;
    case 'v':
      info[i].dir = South;
      break;
    case '<':
      info[i].dir = West;
      break;
    }
  }

  sort(X.begin(), X.end());
  sort(Y.begin(), Y.end());

  X.erase(unique(X.begin(), X.end()), X.end());
  Y.erase(unique(Y.begin(), Y.end()), Y.end());

  // 座標圧縮
  for (int i = 0; i < X.size(); i++) {
    X_MAP[X[i]] = i;
  }
  for (int i = 0; i < Y.size(); i++) {
    Y_MAP[Y[i]] = i;
  }

  int size_X = (int)X.size(), size_Y = (int)Y.size();

  for (int i = 0; i < size_X; i++) {
    for (int k = 0; k < size_Y; k++)
      data[i][k].exist = false;
  }

  // 圧縮済座標上に力点を配置
  for (int i = 0; i < N; i++) {
    data[Y_MAP[info[i].y]][X_MAP[info[i].x]].exist = true;
    data[Y_MAP[info[i].y]][X_MAP[info[i].x]].dir = info[i].dir;

    comp_Y[Y_MAP[info[i].y]].push_back(
        X_MAP[info[i].x]); // 圧縮後のY座標における、X座標の隣接リスト
    comp_X[X_MAP[info[i].x]].push_back(
        Y_MAP[info[i].y]); // 圧縮後のX座標における、Y座標の隣接リスト
  }

  for (int i = 0; i < size_Y; i++)
    sort(comp_Y[i].begin(), comp_Y[i].end());
  for (int i = 0; i < size_X; i++)
    sort(comp_X[i].begin(), comp_X[i].end());

  // 圧縮後の座標系における、隣接リストでのインデックスを計算する
  int left, right, m;
  for (int row = 0; row < size_Y; row++) {
    for (int col = 0; col < size_X; col++) {
      if (data[row][col].exist == false)
        continue;

      // y == rowにおける、x座標のインデックス
      left = 0, right = comp_Y[row].size() - 1, m = (left + right) / 2;
      while (left <= right) {
        if (comp_Y[row][m] == col) {
          data[row][col].y_index = m;
          break;
        } else if (comp_Y[row][m] > col) {
          right = m - 1;
        } else {
          left = m + 1;
        }
        m = (left + right) / 2;
      }

      // x == colにおける、y座標のインデックス
      left = 0, right = comp_X[col].size() - 1, m = (left + right) / 2;
      while (left <= right) {
        if (comp_X[col][m] == row) {
          data[row][col].x_index = m;
          break;
        } else if (comp_X[col][m] > row) {
          right = m - 1;
        } else {
          left = m + 1;
        }
        m = (left + right) / 2;
      }
    }
  }

  int ans = 0;
  int next_y, next_x;
  State state;

  // 初期位置を全探索
  for (int start = 0; start < N; start++) {

    for (int i = 0; i < size_X; i++) {
      for (int k = 0; k < size_Y; k++)
        data[i][k].visited = false;
    }

    int tmp_count = 1;
    data[Y_MAP[info[start].y]][X_MAP[info[start].x]].visited = true;
    state.set(Y_MAP[info[start].y], X_MAP[info[start].x], info[start].dir);

    while (true) {

      next_y = BIG_NUM;
      next_x = BIG_NUM;

      // 次の力点を探す
      switch (state.dir) {
      case North:
        for (int tmp_y = data[state.y][state.x].x_index - 1; tmp_y >= 0;
             tmp_y--) {
          if (data[comp_X[state.x][tmp_y]][state.x].exist == true &&
              data[comp_X[state.x][tmp_y]][state.x].visited == false) {
            next_y = comp_X[state.x][tmp_y];
            next_x = state.x;
            break;
          }
        }
        break;
      case East:
        for (int tmp_x = data[state.y][state.x].y_index + 1;
             tmp_x <= comp_Y[state.y].size() - 1; tmp_x++) {
          if (data[state.y][comp_Y[state.y][tmp_x]].exist == true &&
              data[state.y][comp_Y[state.y][tmp_x]].visited == false) {
            next_y = state.y;
            next_x = comp_Y[state.y][tmp_x];
            break;
          }
        }
        break;
      case South:
        for (int tmp_y = data[state.y][state.x].x_index + 1;
             tmp_y <= comp_X[state.x].size() - 1; tmp_y++) {
          if (data[comp_X[state.x][tmp_y]][state.x].exist == true &&
              data[comp_X[state.x][tmp_y]][state.x].visited == false) {
            next_y = comp_X[state.x][tmp_y];
            next_x = state.x;
            break;
          }
        }
        break;
      case West:
        for (int tmp_x = data[state.y][state.x].y_index - 1; tmp_x >= 0;
             tmp_x--) {
          if (data[state.y][comp_Y[state.y][tmp_x]].exist == true &&
              data[state.y][comp_Y[state.y][tmp_x]].visited == false) {
            next_y = state.y;
            next_x = comp_Y[state.y][tmp_x];
            break;
          }
        }
        break;
      }

      if (next_y == BIG_NUM || next_x == BIG_NUM)
        break;

      data[next_y][next_x].visited = true;
      state.set(next_y, next_x, data[next_y][next_x].dir);
      tmp_count++;
    }

    ans = max(ans, tmp_count);
  }

  printf("%d\\n", ans);

  return 0;
}