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

#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <utility>
#include <vector>
using namespace std;

using P = pair<int, int>;
using dp1P = P;

const int MAX_M = 1000010;

bool prime_table[MAX_M];
map<P, int> cave;
P num2pos[MAX_M];
bool used[MAX_M];

int dp1[MAX_M], dp2[MAX_M];

int dy[4] = {0, 1, 0, -1}, dx[4] = {1, 0, -1, 0};

void sieve() {
  for (int i = 2; i < MAX_M; i++) {
    prime_table[i] = true;
  }
  for (int m = 2; m * m <= MAX_M; m++) {
    if (prime_table[m]) {
      for (int i = 2; i * m < MAX_M; i++) {
        prime_table[i * m] = false;
      }
    }
  }
}

int main() {
  // テヲツエツ榲ァツェツ淌」ツ?ョテヲツァツ凝ァツッツ?
  int num = 1, x = 0, y = 0, dir = 3;
  cave[P(x, y)] = num;
  num2pos[num] = P(x, y);
  num++;

  for (int i = 0; i < MAX_M - 5; i++) {
    int ndir = (dir + 1) % 4, nx = x + dx[ndir], ny = y + dy[ndir];
    // テ・ツ?・テ」ツ?」テ」ツ?ヲテ」ツ??」ツつ凝」ツ?凝・ツ青ヲテ」ツ??
    if (cave.count(P(nx, ny)) == 0) {
      x = nx;
      y = ny;
      dir = ndir;
    } else {
      x = x + dx[dir], y = y + dy[dir];
    }
    cave[P(x, y)] = num;
    num2pos[num] = P(x, y);
    num++;
  }

  sieve();

  int m, n;
  while (cin >> m >> n, m | n) {
    memset(dp1, -1, sizeof(dp1));
    memset(dp2, 0, sizeof(dp2));
    memset(used, false, sizeof(used));

    queue<int> que;
    que.push(n);

    dp1[n] = prime_table[n];
    dp2[n] = prime_table[n] ? n : 0;

    used[n] = true;
    while (!que.empty()) {
      auto num = que.front();
      que.pop();
      // if (dp1[qp.first] > qp.second) continue;

      P pos = num2pos[num];
      for (int ddx = -1; ddx <= 1; ddx++) {
        int nx = pos.first + ddx, ny = pos.second - 1;
        if (cave.count(P(nx, ny)) == 0 || cave[P(nx, ny)] > m)
          continue;
        int nnum = cave[P(nx, ny)], prime_num = dp1[num] + (prime_table[nnum]);

        if (dp1[nnum] < prime_num) {
          dp1[nnum] = prime_num;
          dp2[nnum] = dp1[num];

          if (prime_table[nnum])
            dp2[nnum] = nnum;

          if (!used[nnum]) {
            que.push(nnum);
            used[nnum] = true;
          }
        } else if (dp1[nnum] == prime_num && dp2[nnum] < dp2[num]) {
          dp2[nnum] = dp2[num];

          if (prime_table[nnum])
            dp2[nnum] = nnum;
        }
      }
    }
    int prime_num = 0, last_prime = 0;
    for (int i = 1; i <= m; i++) {
      if (prime_num < dp1[i]) {
        prime_num = dp1[i];
        last_prime = dp2[i];
      } else if (prime_num == dp1[i] && last_prime < dp2[i]) {
        prime_num = dp1[i];
        last_prime = dp2[i];
      }
    }
    cout << prime_num << " " << last_prime << endl;
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <utility>
#include <vector>
using namespace std;

using P = pair<int, int>;
using QP = pair<int, int>; // (テゥツ?づァツつケ, テ・ツ?、)
using dp1P = P;

const int MAX_M = 1000010;

bool prime_table[MAX_M];
map<P, int> cave;
map<int, P> num2pos;

int dp1[MAX_M], dp2[MAX_M];

int dy[4] = {0, 1, 0, -1}, dx[4] = {1, 0, -1, 0};

void sieve() {
  for (int i = 2; i < MAX_M; i++) {
    prime_table[i] = true;
  }
  for (int m = 2; m * m <= MAX_M; m++) {
    if (prime_table[m]) {
      for (int i = 2; i * m < MAX_M; i++) {
        prime_table[i * m] = false;
      }
    }
  }
}

int main() {
  // テヲツエツ榲ァツェツ淌」ツ?ョテヲツァツ凝ァツッツ?
  int num = 1, x = 0, y = 0, dir = 3;
  cave[P(x, y)] = num;
  num2pos[num] = P(x, y);
  num++;

  for (int i = 0; i < MAX_M - 5; i++) {
    int ndir = (dir + 1) % 4, nx = x + dx[ndir], ny = y + dy[ndir];
    // テ・ツ?・テ」ツ?」テ」ツ?ヲテ」ツ??」ツつ凝」ツ?凝・ツ青ヲテ」ツ??
    if (cave.count(P(nx, ny)) == 0) {
      x = nx;
      y = ny;
      dir = ndir;
    } else {
      x = x + dx[dir], y = y + dy[dir];
    }
    cave[P(x, y)] = num;
    num2pos[num] = P(x, y);
    num++;
  }

  sieve();

  int m, n;
  while (cin >> m >> n, m | n) {
    memset(dp1, -1, sizeof(dp1));
    memset(dp2, 0, sizeof(dp2));

    queue<P> que;
    que.push(QP(n, prime_table[n]));

    dp1[n] = prime_table[n];
    dp2[n] = prime_table[n] ? n : 0;

    set<int> set;
    set.insert(n);
    while (!que.empty()) {
      auto qp = que.front();
      que.pop();
      // if (dp1[qp.first] > qp.second) continue;

      P pos = num2pos[qp.first];
      for (int ddx = -1; ddx <= 1; ddx++) {
        int nx = pos.first + ddx, ny = pos.second - 1;
        if (cave.count(P(nx, ny)) == 0 || cave[P(nx, ny)] > m)
          continue;
        int nnum = cave[P(nx, ny)],
            prime_num = dp1[qp.first] + (prime_table[nnum]);

        if (dp1[nnum] < prime_num) {
          dp1[nnum] = prime_num;
          dp2[nnum] = dp1[qp.first];

          if (prime_table[nnum])
            dp2[nnum] = nnum;

          if (set.count(nnum) == 0) {
            que.push(QP(nnum, dp1[nnum]));
            set.insert(nnum);
          }
        } else if (dp1[nnum] == prime_num && dp2[nnum] < dp2[qp.first]) {
          dp2[nnum] = dp2[qp.first];

          if (prime_table[nnum])
            dp2[nnum] = nnum;
        }
      }
    }
    int prime_num = 0, last_prime = 0;
    for (int i = 1; i <= m; i++) {
      if (prime_num < dp1[i]) {
        prime_num = dp1[i];
        last_prime = dp2[i];
      } else if (prime_num == dp1[i] && last_prime < dp2[i]) {
        prime_num = dp1[i];
        last_prime = dp2[i];
      }
    }
    cout << prime_num << " " << last_prime << endl;
  }

  return 0;
}