Problem p03572 (C++)

Buggy submission (status: Memory Limit Exceeded):
/*{{{*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
typedef pair<int, int> PP;
typedef long long LL;
#define pb push_back
#define fr first
#define sc second
#define bitcnt __builtin_popcount
#define all(x) x.begin(), x.end()
inline LL ri() {
  LL x;
  scanf("%lld", &x);
  return x;
}
#define rep2(i, n, ...) for (int i = 0; i < (n); i++)
#define rep3(i, a, b, ...) for (int i = (a); i < (b); i++)
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define rep(...) GET_MACRO(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define drep2(i, n, ...) for (int i = (n)-1; i >= 0; i--)
#define drep3(i, a, b) for (int i = (a)-1; i >= (b); i--)
#define drep(...) GET_MACRO(__VA_ARGS__, drep3, drep2)(__VA_ARGS__)
template <typename T> inline bool smax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> inline bool smin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
/*}}}*/

// mod int
struct mint {
  const static long long mod = 1e9 + 7;
  int x;
  mint() : x(0) {}
  mint(long long x) : x(((x % mod) + mod) % mod){};
  mint operator+=(const mint &a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint operator-=(const mint &a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint operator*=(const mint &a) {
    x = ((LL)x * a.x) % mod;
    return *this;
  }
  mint operator*(const mint &a) { return mint(*this) *= a; }
  mint operator-(const mint &a) { return mint(*this) -= a; }
  mint operator+(const mint &a) { return mint(*this) += a; }
  template <typename T> mint operator*(const T &a) { return mint(*this) *= a; }
  template <typename T> mint operator-(const T &a) { return mint(*this) -= a; }
  template <typename T> mint operator+(const T &a) { return mint(*this) += a; }
  template <typename T> friend mint operator*(T x, const mint &m) {
    return mint(x) *= m;
  }
  template <typename T> friend mint operator-(T x, const mint &m) {
    return mint(x) -= m;
  }
  template <typename T> friend mint operator+(T x, const mint &m) {
    return mint(x) += m;
  }
  bool operator==(const mint &a) const { return x == a.x; }
  operator long long() const { return x; }
};
mint pw(mint a, long long b) {
  mint res(1);
  while (b) {
    if (b & 1)
      res *= a;
    a *= a;
    b >>= 1;
  }
  return res;
}
mint inv(mint a) { return pw(a, mint::mod - 2); }
// mod int

int a[405], b[405], pa[405], pb[405], t[405][405], n;

int tx[405][405], ty[405][405];
mint res[405][405][405][2];

mint &get(int i, int j, int k, int e) {
  int x = tx[j][k];
  int y = ty[j][k];
  // if (x == n || y == n) {
  // cout << i << ' ' << j << ' ' << k << endl;
  //}
  return res[i][x][y][e];
}

int main() {
  cin >> n;
  rep(i, n) cin >> a[i], pa[a[i]] = i;
  rep(i, n) cin >> b[i], pb[b[i]] = i;
  rep(i, n) {
    int s = 0;
    rep(j, n) {
      s += pa[b[j]] <= i;
      t[i + 1][j + 1] = s;
    }
  }
  drep(j, n + 1) drep(k, n + 1) {
    int na = pb[a[j]], nb = pa[b[k]];
    if (j < n && na < k) {
      tx[j][k] = tx[j + 1][k];
      ty[j][k] = ty[j + 1][k];
    } else if (k < n && nb < j) {
      tx[j][k] = tx[j][k + 1];
      ty[j][k] = ty[j][k + 1];
    } else {
      tx[j][k] = j;
      ty[j][k] = k;
    }
  }

  res[0][0][0][0] = 1;
  int m = n / 3;
  rep(i, m + 1) {
    rep(j, i, n) {
      rep(k, i, n) {
        rep(e, 0, 2) {
          if (!res[i][j][k][e])
            continue;
          if (tx[j][k] != j || ty[j][k] != k)
            continue;
          int uniques = j + k - t[j][k];
          int cc = uniques - 2 * i;
          if (cc <= i && cc >= 0) { // valid
            if (a[j] != b[k]) {
              if (i < m) {
                get(i + 1, j + 1, k + 1, 0) += res[i][j][k][e];
              }
              if (cc < i) {
                if (e == 0)
                  get(i, j + 1, k, 0) += res[i][j][k][e] * (i - cc);
                get(i, j, k + 1, 1) += res[i][j][k][e] * (i - cc);
              }
            } else {
              if (cc < i)
                if (e == 0)
                  get(i, j + 1, k + 1, 0) += res[i][j][k][e] * (i - cc);
            }
          }
        }
      }
    }
  }
  // cout << res[2]
  // cout << res[1][2][1] << endl;
  // cout << res[1][1][1] << endl;
  mint ans = res[m][n][n][0] + res[m][n][n][1];
  // cout << res[2][2][3] << ' ' << endl;
  // cout << res[2][3][2] << ' ' << endl;
  // cout << ans << endl;
  rep(i, m) { ans *= (3 * (m - i) - 1) * (3 * (m - i) - 2); }
  cout << ans << endl;
  // cout << res[]
  return 0;
}


Fixed submission:
/*{{{*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
typedef pair<int, int> PP;
typedef long long LL;
#define pb push_back
#define fr first
#define sc second
#define bitcnt __builtin_popcount
#define all(x) x.begin(), x.end()
inline LL ri() {
  LL x;
  scanf("%lld", &x);
  return x;
}
#define rep2(i, n, ...) for (int i = 0; i < (n); i++)
#define rep3(i, a, b, ...) for (int i = (a); i < (b); i++)
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define rep(...) GET_MACRO(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define drep2(i, n, ...) for (int i = (n)-1; i >= 0; i--)
#define drep3(i, a, b) for (int i = (a)-1; i >= (b); i--)
#define drep(...) GET_MACRO(__VA_ARGS__, drep3, drep2)(__VA_ARGS__)
template <typename T> inline bool smax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> inline bool smin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
/*}}}*/

// mod int
struct mint {
  const static long long mod = 1e9 + 7;
  int x;
  mint() : x(0) {}
  mint(long long x) : x(((x % mod) + mod) % mod){};
  mint operator+=(const mint &a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint operator-=(const mint &a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint operator*=(const mint &a) {
    x = ((LL)x * a.x) % mod;
    return *this;
  }
  mint operator*(const mint &a) { return mint(*this) *= a; }
  mint operator-(const mint &a) { return mint(*this) -= a; }
  mint operator+(const mint &a) { return mint(*this) += a; }
  template <typename T> mint operator*(const T &a) { return mint(*this) *= a; }
  template <typename T> mint operator-(const T &a) { return mint(*this) -= a; }
  template <typename T> mint operator+(const T &a) { return mint(*this) += a; }
  template <typename T> friend mint operator*(T x, const mint &m) {
    return mint(x) *= m;
  }
  template <typename T> friend mint operator-(T x, const mint &m) {
    return mint(x) -= m;
  }
  template <typename T> friend mint operator+(T x, const mint &m) {
    return mint(x) += m;
  }
  bool operator==(const mint &a) const { return x == a.x; }
  operator long long() const { return x; }
};
mint pw(mint a, long long b) {
  mint res(1);
  while (b) {
    if (b & 1)
      res *= a;
    a *= a;
    b >>= 1;
  }
  return res;
}
mint inv(mint a) { return pw(a, mint::mod - 2); }
// mod int

int a[405], b[405], pa[405], pb[405], t[405][405], n;

int tx[405][405], ty[405][405];
mint res[405 / 3][405][405][2];

mint &get(int i, int j, int k, int e) {
  int x = tx[j][k];
  int y = ty[j][k];
  // if (x == n || y == n) {
  // cout << i << ' ' << j << ' ' << k << endl;
  //}
  return res[i][x][y][e];
}

int main() {
  cin >> n;
  rep(i, n) cin >> a[i], pa[a[i]] = i;
  rep(i, n) cin >> b[i], pb[b[i]] = i;
  rep(i, n) {
    int s = 0;
    rep(j, n) {
      s += pa[b[j]] <= i;
      t[i + 1][j + 1] = s;
    }
  }
  drep(j, n + 1) drep(k, n + 1) {
    int na = pb[a[j]], nb = pa[b[k]];
    if (j < n && na < k) {
      tx[j][k] = tx[j + 1][k];
      ty[j][k] = ty[j + 1][k];
    } else if (k < n && nb < j) {
      tx[j][k] = tx[j][k + 1];
      ty[j][k] = ty[j][k + 1];
    } else {
      tx[j][k] = j;
      ty[j][k] = k;
    }
  }

  res[0][0][0][0] = 1;
  int m = n / 3;
  rep(i, m + 1) {
    rep(j, i, n) {
      rep(k, i, n) {
        rep(e, 0, 2) {
          if (!res[i][j][k][e])
            continue;
          if (tx[j][k] != j || ty[j][k] != k)
            continue;
          int uniques = j + k - t[j][k];
          int cc = uniques - 2 * i;
          if (cc <= i && cc >= 0) { // valid
            if (a[j] != b[k]) {
              if (i < m) {
                get(i + 1, j + 1, k + 1, 0) += res[i][j][k][e];
              }
              if (cc < i) {
                if (e == 0)
                  get(i, j + 1, k, 0) += res[i][j][k][e] * (i - cc);
                get(i, j, k + 1, 1) += res[i][j][k][e] * (i - cc);
              }
            } else {
              if (cc < i)
                if (e == 0)
                  get(i, j + 1, k + 1, 0) += res[i][j][k][e] * (i - cc);
            }
          }
        }
      }
    }
  }
  // cout << res[2]
  // cout << res[1][2][1] << endl;
  // cout << res[1][1][1] << endl;
  mint ans = res[m][n][n][0] + res[m][n][n][1];
  // cout << res[2][2][3] << ' ' << endl;
  // cout << res[2][3][2] << ' ' << endl;
  // cout << ans << endl;
  rep(i, m) { ans *= (3 * (m - i) - 1) * (3 * (m - i) - 2); }
  cout << ans << endl;
  // cout << res[]
  return 0;
}