Problem:
High-Tech Detective
The problem set document for the Yokohama Chinatown Gluttony Contest was kept in a safe
at the headquarters of the Kanagawa Gourmendies Foundation. It was considered to be quite
secure, but, in the morning of the very day of the contest, the executive director of the foundation found that the document was missing!
The director checked that the document was in the safe when she left the headquarters in the
evening of the day before. To open the door of the headquarters office, a valid ID card has to
be touched on the reader inside or outside of the door. As the door and its lock are not broken, the thief should have used a valid ID card.
Normally, all the entries and exits through the door are recorded with the ID. The system,
however, has been compromised somehow, and some of the recorded ID's are lost.
It is sure that nobody was in the office when the director left, but, many persons visited the
office since then to prepare the contest materials. It is sure that the same ID card was used only once for entry and then once for exit.
The director is planning inquiries to grasp all the visits during the night. You are asked to write a program that calculates the number of possible combinations of ID's to fill the lost parts of the records.
Input
The input consists of a single test case of the following format.
$n$
$c_1$ $x_1$
...
$c_{2n}$ $x_{2n}$
The first line contains an integer $n$ ($1 \leq n \leq 5000$), representing the number of visitors during the night. Each visitor has a unique ID numbered from 1 to $n$. The following $2n$ lines provide (incomplete) entry and exit records in chronological order. The $i$-th line ($1 \leq i \leq 2n$) contains a character $c_i$ and an integer $x_i$ ($0 \leq x_i \leq n$). Here, $c_i$ denotes the type of the event, where $c_i = $
I
and
O
indicate some visitor entered and exited the ofice, respectively. $x_i$ denotes the visitor ID, where $x_i  \geq 1$ indicates the ID of the visitor is $x_i$, and $x_i = 0$ indicates the ID is lost. At
least one of them is 0. It is guaranteed that there is at least one consistent way to fill the lost ID(s) in the records.
Output
Output a single integer in a line which is the number of the consistent ways to fill the lost ID(s) modulo $10^9 + 7$.
Sample Input 1
4
I 1
I 0
O 0
I 0
O 2
I 4
O 0
O 4
Sample Output 1
3
Sample Input 2
3
I 0
I 0
I 0
O 0
O 0
O 0
Sample Output 2
36

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define sz(x) ((int)(x).size())
#define all(x) begin(x), end(x)
#define rep(i, l, r) for (int i = (l), i##end = (r); i <= i##end; ++i)
#define per(i, l, r) for (int i = (l), i##end = (r); i >= i##end; --i)
#ifdef memset0
#define log(...) fprintf(stderr, __VA_ARGS__)
#else
#define log(...) (void(0))
#define endl '\n'
#endif
using namespace std;
using ll = long long;
using lf = long double;
using lll = __int128;
using ull = unsigned long long;
const int N = 1e4 + 10;
const int mod = 1e9 + 7;
struct zint {
  int x;
  zint(int x = 0) : x(x) {}
  explicit zint(ll x) : x(x % mod) {}
  zint operator*(const zint &r) const { return zint((ll)x * r.x); }
  zint operator-(const zint &r) const { return x - r.x < 0 ? x - r.x + mod : x - r.x; }
  zint operator+(const zint &r) const { return x + r.x >= mod ? x + r.x - mod : x + r.x; }
} f[N][N >> 1];
zint fac(int x) {
  zint ret = 1;
  for (int i = 1; i <= x; ++i) ret = ret * i;
  return ret;
}
int m, _op[N], _a[N], ap[N];
int n, op[N], a[N], s[N], num;
string S;
int main() {
#ifdef memset0
  freopen("I.in", "r", stdin);
#endif
  cin.tie(0)->sync_with_stdio(0);
  cin >> m;
  for (int i = 1; i <= (m << 1); ++i) {
    cin >> S >> _a[i];
    _op[i] = (S[0] == 'I');
    ap[_a[i]] |= (1 << _op[i]);
  }
  for (int i = 1; i <= (m << 1); ++i) {
    if (!_a[i]) {
      op[++n] = _op[i], a[n] = 0;
      continue;
    }
    if (ap[_a[i]] == 3) continue;
    op[++n] = _op[i], a[n] = _a[i];
  }
  /*log("n=%d\n", n);
  for (int i = 1; i <= n; ++i) {
    log("%c %d\n", "OI"[op[i]], a[i]);
  }*/
  for (int i = 1; i <= m; ++i)
    if (!ap[i]) ++num;
  for (int i = 1; i <= n; ++i) s[i] = s[i - 1] + (op[i] ? 1 : -1);
  f[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j <= s[i - 1]; ++j)
      if (f[i - 1][j].x) {
        if (op[i]) {
          f[i][j] = f[i][j] + f[i - 1][j];
          if (!a[i]) f[i][j + 1] = f[i][j + 1] + f[i - 1][j];
        } else {
          if (a[i]) {
            if (!j) continue;
            f[i][j - 1] = f[i][j - 1] + f[i - 1][j] * j;
          } else {
            f[i][j] = f[i][j] + f[i - 1][j] * (s[i - 1] - j);
          }
        }
      }
    /*for (int j = 0; j <= s[i]; ++j) {
      log("F %d %d=%d\n", i, j, f[i][j].x);
    }*/
  }
  cout << (f[n][0] * fac(num)).x << "\n";
}
accuracy: 1
time_ms: 60
memory_kb: 199308
final_rank: 18

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// using namespace zawa;
#include "atcoder/modint"
using mint = atcoder::modint1000000007;
bool valid(const std::string& s) {
    int bal = 0;
    for (int i = 0 ; i < (int)s.size() ; i++) {
        bal += (s[i] == '(' ? 1 : -1);
        if (bal < 0) return false;
    }
    return bal == 0;
}
mint solve(const std::string& s, const std::vector<bool>& fix) {
    // std::cout << "solve " << s << std::endl;
    assert(valid(s));
    const int n = (int)s.size();
    std::vector<mint> dp(n/2 + 1);
    dp[0] = 1;
    for (int i = 0, fix_l = 0, free_l = 0, free_r = 0 ; i < n ; i++) {
        std::vector<mint> next(n/2 + 1);
        if (s[i] == '(') {
            int up = !fix[i];
            for (int j = 0 ; j + up < (int)next.size() ; j++) next[j + up] += dp[j];
            fix_l += fix[i];
            free_l += (int)fix[i] ^ 1;
        }
        else {
            if (fix[i]) {
                for (int j = 1 ; j < (int)next.size() ; j++) {
                    next[j - 1] += dp[j] * j;
                }
                free_l--;
            }
            else {
                for (int j = 0 ; j <= free_l ; j++) {
                    if (j - 1 >= 0) next[j - 1] += dp[j] * j;
                    // ここがわからん
                    int u = free_l - j;
                    if (0 <= u and u <= free_r) next[j] += dp[j] * (fix_l - (free_r - u));
                }
                free_r++;
            }
        }
        dp = std::move(next);
        // for (auto d : dp) std::cout << d.val() << ' ';
        // std::cout << std::endl;
    }
    return dp[0];
}
int N, X[5010*2], cnt[5010];
std::string S;
mint solve(int l, int r) {
    // std::cout << "solve " << l << ' ' << r << std::endl;
    std::string T;
    std::vector<bool> fix;
    for (int i = l ; i < r ; i++) if (X[i] == -1 or cnt[X[i]] < 2) {
        T += S[i];
        fix.push_back(X[i] != -1);
    }
    return solve(T, fix);
}
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> N;
    for (int i = 0 ; i < 2 * N ; i++) {
        char c;
        std::cin >> c >> X[i];
        X[i]--;
        if (X[i] >= 0) cnt[X[i]]++;
        S += c == 'I' ? '(' : ')';
    }
    mint ans = 1;
    int not_app = std::count(cnt, cnt + N, 0);
    for (int i = 1 ; i <= not_app ; i++) ans *= i;
    for (int i = 0, bal = 0, l = 0 ; i < 2 * N ; i++) {
        bal += S[i] == '(' ? 1 : -1;
        assert(bal >= 0);
        if (bal == 0) {
            ans *= solve(l, i + 1);
            l = i + 1;
        }
    }
    std::cout << ans.val() << '\n';
}
accuracy: 1
time_ms: 70
memory_kb: 3712
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define ov4(a, b, c, d, name, ...) name
#define rep3(i, a, b, c) for(ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for(ll i = (a)-1; i >= (b); i--)
#define fore(e, v) for(auto&& e : v)
#define all(a) begin(a), end(a)
#define si(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template<typename T, typename S> bool chmin(T& a, const S& b) { return a > b ? a = b, 1 : 0; }
template<typename T, typename S> bool chmax(T& a, const S& b) { return a < b ? a = b, 1 : 0; }

const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;

#define i128 __int128_t

struct _ {
    _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

constexpr int MOD = 1000000007;

void add(int& a, const int& b) {
    a += b;
    if (a >= MOD) a -= MOD;
}

int main() {
    ll N;
    cin >> N;
    using vpi = vector<pii>;
    vpi A(2 * N);
    vpi IO(N, {-1, -1});
    constexpr ll IN = 0;
    constexpr ll OUT = 1;
    
    rep(i, 2 * N) {
        char c; ll x;
        cin >> c >> x;
        x--;
        if (c == 'I') {
            A[i] = {IN, x};
            if (x >= 0) IO[x].first = i;
        } else {
            A[i] = {OUT, x};
            if (x >= 0) IO[x].second = i;
        }
    }

    ll in_d = 0, out_d = 0, not_d = 0;
    rep(x, N) {
        auto [i, o] = IO[x];
        if (i != -1 && o != -1) continue;
        else if (i == -1 && o != -1) out_d++;
        else if (i != -1 && o == -1) in_d++;
        else not_d++;
    }

    using vvl = vector<vl>;
    ll inside = 0;
    ll out_d_plus_not_d = out_d + not_d; 
    vi dp(N + 1);
    // dp[inside_out_d] = val
    dp[0] = 1;

    rep(t, 2 * N) {
        auto [c, x] = A[t];
        // cout << "c, x: " << c << " " << x << "\n";
        if (x != -1) {
            auto [i, o] = IO[x];
            if (i != -1 && o != -1) continue;
            // cout << "i, o: " << i << " " << o << "\n";
        }

        vi ndp(N + 1);
        if (c == IN) {
            rep (i, N + 1) {
                if (dp[i] == 0) continue;
                if (x != -1) {
                    add(ndp[i], dp[i]);
                } else {
                    add(ndp[i + 1], dp[i]);
                    ll tmp = out_d_plus_not_d - (out_d - i);
                    // cout << "tmp: " << tmp << "\n";
                    add(ndp[i], (tmp * dp[i]) % MOD);
                }
            }
            if (x == -1) out_d_plus_not_d--;
            inside++;
        } else {
            rep (i, N + 1) {
                if (dp[i] == 0) continue;
                if (x != -1) {
                    if (i > 0) add(ndp[i - 1], (i * dp[i]) % MOD);
                } else {
                    ll tmp = inside - i;
                    add(ndp[i], (tmp * dp[i]) % MOD);
                }
            }
            if (x != -1) out_d_plus_not_d++;
            inside--;
        }
        swap(dp, ndp);
        // cout << "dp: \n";
        // rep (i, N + 1) cout << dp[i] << " ";
        // cout << "\n";
    }
    int ans = dp[0];
    cout << ans << "\n";
}
accuracy: 1
time_ms: 40
memory_kb: 3840
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

template <unsigned mod = 1000000007> struct fp {
    unsigned v;
    static constexpr int get_mod() {
        return mod;
    }
    constexpr unsigned inv() const {
        assert(v != 0);
        int x = v, y = mod, p = 1, q = 0, t = 0, tmp = 0;
        while (y > 0) {
            t = x / y;
            x -= t * y, p -= t * q;
            tmp = x, x = y, y = tmp;
            tmp = p, p = q, q = tmp;
        }
        if (p < 0)
            p += mod;
        return p;
    }
    constexpr fp(ll x = 0) : v(x >= 0 ? x % mod : (mod - (-x) % mod) % mod) {}
    fp operator-() const {
        return fp() - *this;
    }
    fp pow(ull t) {
        fp res = 1, b = *this;
        while (t) {
            if (t & 1)
                res *= b;
            b *= b;
            t >>= 1;
        }
        return res;
    }
    fp &operator+=(const fp &x) {
        if ((v += x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator-=(const fp &x) {
        if ((v += mod - x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator*=(const fp &x) {
        v = ull(v) * x.v % mod;
        return *this;
    }
    fp &operator/=(const fp &x) {
        v = ull(v) * x.inv() % mod;
        return *this;
    }
    fp operator+(const fp &x) const {
        return fp(*this) += x;
    }
    fp operator-(const fp &x) const {
        return fp(*this) -= x;
    }
    fp operator*(const fp &x) const {
        return fp(*this) *= x;
    }
    fp operator/(const fp &x) const {
        return fp(*this) /= x;
    }
    bool operator==(const fp &x) const {
        return v == x.v;
    }
    bool operator!=(const fp &x) const {
        return v != x.v;
    }
    friend istream &operator>>(istream &is, fp &x) {
        return is >> x.v;
    }
    friend ostream &operator<<(ostream &os, const fp &x) {
        return os << x.v;
    }
};

// template <unsigned mod> void rd(fp<mod> &x) {
//     fastio::rd(x.v);
// }
// template <unsigned mod> void wt(fp<mod> x) {
//     fastio::wt(x.v);
// }

template <typename T> T Inv(ll n) {
    static const int md = T::get_mod();
    static vector<T> buf({0, 1});
    assert(n > 0);
    n %= md;
    while (SZ(buf) <= n) {
        int k = SZ(buf), q = (md + k - 1) / k;
        buf.push_back(buf[k * q - md] * q);
    }
    return buf[n];
}

template <typename T> T Fact(ll n, bool inv = 0) {
    static const int md = T::get_mod();
    static vector<T> buf({1, 1}), ibuf({1, 1});
    assert(n >= 0 and n < md);
    while (SZ(buf) <= n) {
        buf.push_back(buf.back() * SZ(buf));
        ibuf.push_back(ibuf.back() * Inv<T>(SZ(ibuf)));
    }
    return inv ? ibuf[n] : buf[n];
}

template <typename T> T nPr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nCr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(r, inv ^ 1) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nHr(int n, int r, bool inv = 0) {
    return nCr<T>(n + r - 1, r, inv);
}

/**
 * @brief Modint
 */

using Fp = fp<1000000007>;

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N;
    cin >> N;
    vector<int> B(N*2), A(N*2);
    rep(i,0,N*2) {
        char C;
        cin >> C;
        if (C == 'I') B[i] = 0;
        else B[i] = 1;
        cin >> A[i];
        A[i]--;
    }
    vector<vector<int>> C(N, vector<int>(2,-1));
    rep(i,0,N*2) {
        if (A[i] != -1) C[A[i]][B[i]] = i;
    }
    vector<int> D;
    rep(i,0,N) {
        if (C[i][0] == -1 && C[i][1] == -1) D.push_back(0);
        if (C[i][0] == -1 && C[i][1] != -1) D.push_back(1);
        if (C[i][0] != -1 && C[i][1] == -1) D.push_back(2);
        if (C[i][0] != -1 && C[i][1] != -1) D.push_back(3);
    }
    int SI = 0, SD = 0;
    rep(i,0,N) {
        if (D[i] == 0) SI++;
        if (D[i] == 1) SI++, SD++;
    }
    vector<int> E(N*2+1,0);
    rep(i,0,N*2) {
        if (A[i] != -1 && D[A[i]] == 3) {
            E[i+1] = E[i];
            continue;
        }
        if (B[i] == 0) E[i+1] = E[i]+1;
        else E[i+1] = E[i]-1;
    }
    vector<Fp> DP(N+1,0);
    DP[0] = 1;
    int CI = 0, CD = 0;
    rep(i,0,N*2) {
        if (A[i] != -1 && D[A[i]] == 3) continue;
        vector<Fp> NewDP(N+1,0);
        if (B[i] == 0) {
            if (A[i] == -1) {
                rep(j,0,N+1) {
                    if (DP[j] == 0) continue;
                    int X = SI - CI;
                    int Y = SD - (CD + j);
                    if (X - Y >= 1) {
                        NewDP[j] += DP[j] * (X-Y);
                    }
                    if (Y >= 1) {
                        NewDP[j+1] += DP[j];
                    }
                }
            }
            else {
                NewDP = DP;
            }
        }
        else {
            rep(j,0,N+1) {
                if (DP[j] == 0) continue;
                if (A[i] == -1) {
                    if (E[i] - j >= 1) {
                        NewDP[j] += DP[j] * (E[i]-j);
                    }
                }
                else {
                    if (j >= 1) {
                        NewDP[j-1] += DP[j] * j;
                    }
                }
            }
        }
        if (B[i] == 0 && A[i] == -1) CI++;
        if (B[i] == 1 && A[i] != -1 && D[A[i]] == 1) CD++;
        swap(DP, NewDP);
    }
    cout << DP[0] << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 3936
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9+7;

void add(ll &a,const ll b){
	a += b;
	a %= mod;
	return;
}

vector<ll> dp(10001);
vector<ll> ndp(10001);

int main(){
	int N; cin >> N;
	N *= 2;
	vector<char> c(N);
	vector<int> A(N);
	vector<int> cnt(N);
	for(int i = 0; i < N; i++){
		cin >> c[i] >> A[i];
		if(A[i] != 0)cnt[A[i]-1]++;
	}
	vector<char> nc;
	vector<int> nA;
	for(int i = 0; i < N; i++){
		if(A[i] != 0 && cnt[A[i]-1] == 2)continue;
		nc.push_back(c[i]);
		nA.push_back(A[i]);
	}
	swap(c, nc);
	swap(A, nA);
	N = A.size();
	vector<int> cntI(N);
	vector<int> cntO(N);
	for(int i = 0; i < N; i++){
		if(c[i] == 'I')cntI[i]++;
		else cntO[i]++;
		if(i == 0)continue;
		cntI[i] += cntI[i-1];
		cntO[i] += cntO[i-1];
	}
	dp[0] = 1;
	for(int i = 0; i < N; i++){
		for(int j = 0; j <= N; j++)ndp[j] = 0;
		for(int j = 0; j <= N; j++){
			if(c[i] == 'I'){
				if(A[i] == 0){
					if(j+1 <= N)add(ndp[j+1] , dp[j]);		
				}
				else{
					add(ndp[j] , dp[j]);
				}
			}
			else{
				if(A[i] == 0){
					int k = cntI[i-1] - cntO[i-1] - j;
					if(k < 0)continue;
					add(ndp[j], dp[j]*k);
					if(j-1 >= 0)add(ndp[j-1], dp[j]*j);
				}
				else{
					if(j-1 >= 0)add(ndp[j-1], dp[j]*j);
				}
			}
		}
		swap(dp, ndp);
	}
	int x = N/2;
	for(int i = 0; i < N; i++){
		if(A[i] != 0)x--;
	}
	ll ans = dp[0];
	for(int i = 1; i <= x; i++){
		ans *= i;
		ans %= mod;
	}
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 3796
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9+7;

void add(ll &a,const ll b){
	a += b;
	a %= mod;
	return;
}

vector<ll> dp(5050);
vector<ll> ndp(5050);

int main(){
	int N; cin >> N;
	N *= 2;
	vector<char> c(N);
	vector<int> A(N);
	vector<int> cnt(N);
	for(int i = 0; i < N; i++){
		cin >> c[i] >> A[i];
		if(A[i] != 0)cnt[A[i]-1]++;
	}
	vector<char> nc;
	vector<int> nA;
	for(int i = 0; i < N; i++){
		if(A[i] != 0 && cnt[A[i]-1] == 2)continue;
		nc.push_back(c[i]);
		nA.push_back(A[i]);
	}
	swap(c, nc);
	swap(A, nA);
	N = A.size();
	vector<int> cntI(N);
	vector<int> cntO(N);
	for(int i = 0; i < N; i++){
		if(c[i] == 'I')cntI[i]++;
		else cntO[i]++;
		if(i == 0)continue;
		cntI[i] += cntI[i-1];
		cntO[i] += cntO[i-1];
	}
	dp[0] = 1;
	for(int i = 0; i < N; i++){
		for(int j = 0; j <= N; j++)ndp[j] = 0;
		for(int j = 0; j <= N; j++){
			if(c[i] == 'I'){
				if(A[i] == 0){
					if(j+1 <= N)add(ndp[j+1] , dp[j]);		
				}
				else{
					add(ndp[j] , dp[j]);
				}
			}
			else{
				if(A[i] == 0){
					int k = cntI[i-1] - cntO[i-1] - j;
					if(k < 0)continue;
					add(ndp[j], dp[j]*k);
					if(j-1 >= 0)add(ndp[j-1], dp[j]*j);
				}
				else{
					if(j-1 >= 0)add(ndp[j-1], dp[j]*j);
				}
			}
		}
		swap(dp, ndp);
	}
	int x = N/2;
	for(int i = 0; i < N; i++){
		if(A[i] != 0)x--;
	}
	ll ans = dp[0];
	for(int i = 1; i <= x; i++){
		ans *= i;
		ans %= mod;
	}
	cout << ans << endl;

	return 0;
}
accuracy: 0.48
time_ms: 30
memory_kb: 3604
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
const ll MOD = 1e9 + 7;

int main()
{
  int N; cin >> N;
  vector<array<int, 2>> inout(2 * N);
  for (int i = 0; i < 2*N; ++i)
  {
    char c; cin >> c;
    int id; cin >> id;
    
    if (c == 'I') inout[i] = {1, id};
    else inout[i] = {0, id};
  }
  
  vector<int> height(2 * N + 1, 0);
  vector<int> used(N + 1, 0);
  for (int i = 0; i < 2 * N; ++i)
  {
    auto [c, id] = inout[i];
    if (id > 0) used[id] += (1<<c);
  }
  // used[i] = 0 : none, 1 : out, 2 : in, 3 : in & out
  for (int i = 0; i < 2 * N; ++i)
  {
    auto [c, id] = inout[i];
    height[i+1] = height[i];
    if (used[id] == 3) continue;
    if (inout[i][0]) height[i+1]++;
    else height[i+1]--;
  }
  
  vector<ll> dp(2 * N, 0);
  vector<ll> ndp = dp;
  dp[0] = 1;
  for (int i = 0; i < 2 * N; ++i)
  {
    for (int in = 0; in < 2 * N; ++in)
    {
      auto [c, id] = inout[i];
      if (used[id] == 3)
      {
        ndp[in] = dp[in];
        continue;
      }
      
      if (c == 1)
      {
        if (id == 0) ndp[in] += dp[in];
        else
        {
          if (in + 1 < 5010) ndp[in + 1] += dp[in];
        }
      }
      else
      {
        int zero = max(0, height[i] - in);
        if (id == 0)
        {
          ndp[in] += dp[in] * zero;
          ndp[in] %= MOD;
          if (in > 0) ndp[in - 1] += dp[in] * in;
          if (in > 0) ndp[in - 1] %= MOD;
        }
        else
        {
          ndp[in] += dp[in] * zero;
          ndp[in] %= MOD;
        }
        
      }
      
    }
    swap(dp, ndp);
    ndp.assign(2 * N, 0);
  }
  
  
  ll res = dp[0] % MOD;
  {
    ll zeros = 0;
    for (int i = 1; i <= N; ++i)
    {
      if (used[i] == 0) zeros++;
    }
    for (int n = 1; n <= zeros; ++n)
    {
      res *= n;
      res %= MOD;
    }
  }
  
  cout << res << endl;
  
  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 3740
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvvb = vector<vvb>;
using vvvvb = vector<vvvb>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}
const ll mod = 1e9 + 7;





vector<ll> fact, factinv, inv;
void prenCkModp(ll n) {
    fact.resize(n + 5);
    factinv.resize(n + 5);
    inv.resize(n + 5);
    fact[0] = fact[1] = 1;
    factinv[0] = factinv[1] = 1;
    inv[1] = 1;
    for (ll i = 2; i < n + 5; i++) {
        fact[i] = (fact[i - 1] * i) % mod;
        inv[i] = (mod - ((inv[mod % i] * (mod / i) % mod) % mod) + mod) % mod;
        factinv[i] = (factinv[i - 1] * inv[i]) % mod;
    }
}
ll nCk(ll n, ll k) {
    if (n < k || k < 0) return 0;
    return (fact[n] * ((factinv[k] * factinv[n - k] % mod) % mod) % mod) % mod;
}

ll modpow(ll a, ll n) {
    a %= mod;
    if (n == 0)return 1;
    if (n == 1)return a;
    if (n % 2 == 1)return (a * modpow(a, n / 2)) % mod;
    ll t = modpow(a, n / 2);
    return (t * t) % mod;
}




int main() {
    ll N;
    cin >> N;
    vll D(N, 0);
    vll X(N * 2);
    vector<char> B(N * 2);
    rep(i, N * 2) {
        char C;
        ll id;
        cin >> C >> id;
        id--;
        B[i] = C;
        X[i] = id;
        if (id < 0)continue;
        if (D[id] == 2) {
            cout << 0 << endl;
            return 0;
        }
        D[id] += (C == 'I' ? 1 : 2);
    }
    // vvll DP(2 * N + 1, vll(N + 1, 0));
    vll DP(N+1,0);
    DP[0]=1;
    // DP[0][0] = 1;
    ll cnt = 0,bnt=0;
    rep(i, 2 * N) {
        vll NDP(N+1,0);
        if (B[i] == 'I'){
            if(X[i]!=-1&&D[X[i]]==3){

            }
            else cnt++;
        }
        if(B[i]=='O'&&X[i]==-1){
            cnt--;
        }
        rep(j, N + 1) {
            if (X[i] == -1) {
                if(B[i]=='I'){
                    NDP[j] += DP[j];
                    NDP[j] %= mod;
                }
                if (j != 0 && B[i] == 'O'){
                    NDP[j - 1] += DP[j] * j;
                    NDP[j - 1] %= mod;
                }
                if(j!=N&&B[i]=='I'){
                    NDP[j+1] += DP[j];
                    NDP[j+1] %= mod;
                }
            }
            else if (D[X[i]] == 1) {
                if (j == N)continue;
                NDP[j + 1] += DP[j];
                NDP[j + 1] %= mod;
            }
            else if (D[X[i]] == 2) {
                if(cnt>=j+bnt)NDP[j] += DP[j] * (cnt -j-bnt);
                NDP[j] %= mod;
            }
            else if (D[X[i]] == 3) {
                NDP[j] += DP[j];
                NDP[j] %= mod;
            }
        }
        if(X[i]!=-1&&D[X[i]]==2)bnt++;
        swap(DP,NDP);
    }
    ll an = DP[0];
    cnt=1;
    rep(i,N)if(D[i]==0){
        an=(an*cnt)%mod;
        cnt++;
    }
    cout << an << endl;
}
accuracy: 1
time_ms: 100
memory_kb: 3652
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
template<int mod>istream &operator>>(istream &is,static_modint<mod> &a){long long b;is>>b;a=b;return is;}
istream &operator>>(istream &is,modint &a){long long b;cin>>b;a=b;return is;}
#endif
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) static_cast<void>(0)
#define debugg(...) static_cast<void>(0)
#define esper(...) static_cast<void>(0)
template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;}
#endif
using ll=long long;
using ull=unsigned long long;
using P=pair<ll,ll>;
template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>;
template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);}
template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);}
template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;}
template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;}
template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;}
template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;}
template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;}
#define reps(i,a,n) for(int i=(a);i<(n);i++)
#define rep(i,n) reps(i,0,n)
#define all(x) x.begin(),x.end()
#define pcnt(x) __builtin_popcountll(x)
#define fin(x) return cout<<x<<'\n',static_cast<void>(0)
ll myceil(ll a,ll b){return (a+b-1)/b;}
template<typename T,size_t n,size_t id=0>
auto vec(const int (&d)[n],const T &init=T()){
  if constexpr (id<n)return vector(d[id],vec<T,n,id+1>(d,init));
  else return init;
}
void SOLVE();
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout<<fixed<<setprecision(16);
  #ifdef LOCAL
  clock_t start=clock();
  #endif
  int testcase=1;
  //cin>>testcase;
  for(int i=0;i<testcase;i++){
    SOLVE();
  }
  #ifdef LOCAL
  cerr<<"time:";
  cerr<<(clock()-start)/1000;
  cerr<<"ms\n";
  #endif
}
template<int m>
struct montgomery_modint{
private:
  using mint=montgomery_modint;
  using i32=int32_t;
  using u32=uint32_t;
  using u64=uint64_t;
  static constexpr u32 get_r(){
    u32 ret=m;
    for(u32 i=0;i<4;i++)ret*=2-m*ret;
    return ret;
  }
  static_assert(m>2);
  static_assert(m<(1<<30));
  static_assert(m&1);
  static constexpr u32 r1=get_r();
  static constexpr u32 r2=-u64(m)%m;
  u32 v;
  static constexpr u32 reduce(const u64 &a){
    return (a+u64(u32(a)*u32(-r1))*m)>>32;
  }
public:
  montgomery_modint():v(0){}
  montgomery_modint(ll a):v(reduce(u64(a%m+m)*r2)){}
  static mint raw(int a){
    mint ret;
    ret.v=reduce(u64(a)*r2);
    return ret;
  }
  u32 val()const{
    u32 ret=reduce(v);
    return ret>=m?ret-m:ret;
  }
  static constexpr int mod(){return m;}
  mint &operator+=(const mint &b){
    if(i32(v+=b.v-m*2)<0)v+=m*2;
    return *this;
  }
  mint &operator-=(const mint &b){
    if(i32(v-=b.v)<0)v+=m*2;
    return *this;
  }
  mint &operator*=(const mint &b){
    v=reduce(u64(v)*b.v);
    return *this;
  }
  mint &operator/=(const mint &b){
    *this*=b.inv();
    return *this;
  }
  mint operator+()const{return *this;}
  mint operator-()const{return mint()-*this;}
  friend mint operator+(const mint &a,const mint &b){return mint(a)+=b;}
  friend mint operator-(const mint &a,const mint &b){return mint(a)-=b;}
  friend mint operator*(const mint &a,const mint &b){return mint(a)*=b;}
  friend mint operator/(const mint &a,const mint &b){return mint(a)/=b;}
  friend bool operator==(const mint &a,const mint &b){return (a.v>=m?a.v-m:a.v)==(b.v>=m?b.v-m:b.v);}
  friend bool operator!=(const mint &a,const mint &b){return !(a==b);}
  mint pow(ll n)const{
    mint ret=1,a(*this);
    while(n){
      if(n&1)ret*=a;
      a*=a;
      n>>=1;
    }
    return ret;
  }
  inline mint inv()const{
    return pow(m-2);
  }
  friend istream &operator>>(istream &is,mint &b){
    ll a;
    is>>a;
    b=mint(a);
    return is;
  }
  friend ostream &operator<<(ostream &os,const mint &b){
    os<<b.val();
    return os;
  }
};
using mint=montgomery_modint<1000000007>;
void SOLVE(){
  int n;
  cin>>n;
  vector<int>cnt(n,0);
  vector<pair<char,int>>a(n*2);
  rep(i,n*2){
    cin>>a[i];
    if(a[i].second!=0)cnt[a[i].second-1]++;
  }
  {
    vector<pair<char,int>>b;
    rep(i,n*2)if(a[i].second==0||cnt[a[i].second-1]!=2)b.push_back(a[i]);
    swap(a,b);
  }
  debug(a);
  assert(a.size()%2==0);
  n=a.size()/2;
  vector<mint>dp(n+1,0);
  dp[0]=1;
  int ma=0;
  rep(i,n*2){
    vector<mint>ep(n+1,0);
    auto [c,v]=a[i];
    if(c=='I'){
      if(v==0){
        rep(j,n)ep[j+1]+=dp[j];
      }
      else{
        rep(j,n+1)ep[j]+=dp[j];
      }
      ma++;
    }
    else{
      if(v==0){
        rep(j,n+1){
          if(ma-j>0)ep[j]+=dp[j]*(ma-j);
          if(j)ep[j-1]+=dp[j]*j;
        }
      }
      else{
        rep(j,n+1){
          if(j)ep[j-1]+=dp[j]*j;
        }
      }
      ma--;
    }
    swap(dp,ep);
  }
  int c=0;
  rep(i,cnt.size())c+=cnt[i]==0;
  mint ans=dp[0];
  reps(i,1,c+1)ans*=i;
  cout<<ans.val()<<endl;
}
accuracy: 1
time_ms: 110
memory_kb: 3720
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(ll i = 0; i < n; i++)
#define all(a) (a).begin(),(a).end()


int main(){
    ll n;
    cin >> n;
    ll mod=1000000007;
    vector<char> a(2*n);
    vector<ll> b(2*n);
    vector<ll> t(n);
    vector<ll> r(n);
    for(int i=0;i<2*n;i++){
        cin >> a[i] >> b[i];
        b[i]--;
        if(b[i]==-1)continue;
        if(a[i]=='I')t[b[i]]++;
        else r[b[i]]++;
    }
    ll ans=1;
    ll p=0;
    for(int i=0;i<n;i++){
        if(t[i]==0&&r[i]==0){
            p++;
            ans*=p;
            ans%=mod;
        }
    }
    vector<ll> dp(1,ans);
    ll s=0;
    for(int i=0;i<2*n;i++){
        
        if(a[i]=='I'){
            if(b[i]!=-1&&r[b[i]]==1)continue;
            s++;
            vector<ll> ndp(s+1);
            if(b[i]==-1){
            for(int j=0;j<s;j++){
                ndp[j]=dp[j];
            }
            }
            else{
                for(int j=0;j<s;j++){
                    ndp[j+1]=dp[j];
            }
            }
            dp=ndp;
        }
        else{
            if(b[i]!=-1&&t[b[i]]==1)continue;
            s--;
            vector<ll> ndp(s+1);
            if(b[i]==-1){
            for(int j=0;j<s+1;j++){
                ndp[j]+=dp[j]*(s+1-j);
                ndp[j]%=mod;
            }
            for(int j=0;j<s+1;j++){
                ndp[j]+=dp[j+1]*(j+1);
                ndp[j]%=mod;
            }
            }
            else{
            for(int j=0;j<s+1;j++){
                ndp[j]+=dp[j]*(s+1-j);
                ndp[j]%=mod;
            
            }
            }
            dp=ndp;
        }
    }
    cout << dp[0] << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 3728
final_rank: 2

code_snippet: #include <bits/stdc++.h>

#define rep(i,s,n) for(int i = int(s); i < int(n); i++)
#define rrep(i,s,n) for(int i = int(n) - 1; i >= int(s); i--)
#define all(v) (v).begin(), (v).end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template<class T>
bool chmin(T &a, T b) {
    if(a <= b) return false;
    a = b;
    return true;
}

template<class T>
bool chmax(T &a, T b) {
    if(a >= b) return false;
    a = b;
    return true;
}

template<ll m> struct modint {
    using mint = modint;
    ll a;
    modint(ll x = 0) : a((x % m + m) % m) {}
    static constexpr ll mod(){
        return m;
    }
    ll val() const {
        return a;
    }
    ll &val(){
        return a;
    }
    mint pow(ll n) const {
        mint res = 1;
        mint x = a;
        while (n){
            if (n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        return res;
    }
    mint inv() const {
        return pow(mod-2);
    }
    mint &operator+=(const mint rhs){
        a += rhs.a;
        if (a >= m) a -= m;
        return *this;
    }
    mint &operator-=(const mint rhs){
        if (a < rhs.a) a += m;
        a -= rhs.a;
        return *this;
    }
    mint &operator*=(const mint rhs){
        a = a * rhs.a % m;
        return *this;
    }
    mint &operator/=(const mint rhs){
        (*this) *= rhs.inv();
        return *this;
    }
    friend mint operator+(const mint &lhs, const mint &rhs){
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint &lhs, const mint &rhs){
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint &lhs, const mint &rhs){
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint &lhs, const mint &rhs){
        return mint(lhs) /= rhs;
    }
};

using mint = modint<1'000'000'007>;

int main() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int n;
    std::cin >> n;
    std::vector<int> table(n, 0);
    std::vector<std::pair<int,int>> cx(2*n);
    for(auto &[c, x]: cx) {
        char a;
        std::cin >> a >> x;
        if(a == 'I') {
            c = 0;
        }
        else c = 1;
        x--;
        if(x >= 0) table[x]++;
    }
    int q = 0;
    rep(i,0,n) {
        if(table[i] == 0) q++;
    }
    std::vector<mint> dp(n+1, 0);
    int sum = 0;
    int in = 0, out = 0;
    dp[0] = 1;
    for(auto [c, x]: cx) {
        if(x < 0) {
            std::vector<mint> nxt(n+1, 0);
            rep(j,0,n+1) {
                int i = sum - j;
                if(i < 0) break;
                if(c == 0) {
                    if(j < n) {
                        nxt[j + 1] += dp[j];
                    }
                    int cnt = q - (in - j - out);
                    if(cnt > 0) {
                        nxt[j] += dp[j] * cnt;
                    }
                }
                else {
                    if(i > 0) {
                        nxt[j] += dp[j] * i;
                    }
                }
            }
            std::swap(dp, nxt);
            if(c == 0) in++;
        }
        else {
            if(table[x] == 2) continue;
            std::vector<mint> nxt(n+1, 0);
            rep(j,0,n+1) {
                int i = sum - j;
                if(i < 0) break;
                if(c == 0) {
                    nxt[j] += dp[j];
                }
                else {
                    if(j > 0) nxt[j-1] += dp[j] * j;
                }
            }
            std::swap(dp, nxt);
            if(c == 1) out++;
        }
        sum += (c == 0 ? 1 : -1);
    }
    std::cout << dp[0].val() << '\n';
}
accuracy: 1
time_ms: 90
memory_kb: 3624
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int mod=1e9+7;
ll fac[6000];

void ch(ll &a,ll b){
  a=(a+b)%mod;
}
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  fac[0]=fac[1]=1;
  for(int i=2;i<6000;i++){
    fac[i]=fac[i-1]*i%mod;
  }
  int N;
  cin>>N;
  vector<pair<char,int>>A(N*2);
  for(auto &i:A)cin>>i.first>>i.second;
  unordered_set<int>IO,I,O;
  for(int i=0;i<N*2;i++){
    if(A[i].second!=0){
      if(A[i].first=='I'){
        I.insert(A[i].second);
      }else{
        O.insert(A[i].second);
      }
    }
  }
  for(auto i:I){
    if(O.find(i)!=O.end()){
      IO.insert(i);
    }
  }
  vector dp(2,vector(N+1,0ll));
  ll cntI=0;
  dp[0][0]=1;
  for(int i=0;i<N*2;i++){
    if(IO.find(A[i].second)!=IO.end()){
      continue;
    }
    for(int j=0;j<=N;j++){
      if(cntI<j)break;
      if(A[i].first=='I'){
        if(A[i].second==0){
          ch(dp[1][j+1],dp[0][j]);
        }else{
          ch(dp[1][j],dp[0][j]);
        }
      }else{
        if(A[i].second==0){
          ch(dp[1][j-1],dp[0][j]*j);
          ch(dp[1][j],dp[0][j]*(cntI-j));
        }else{
          ch(dp[1][j-1],dp[0][j]*j);
        }
      }
    }
    if(A[i].first=='I')cntI+=1;
    else cntI-=1;
    for(int j=0;j<=N;j++){
      dp[0][j]=dp[1][j];
      dp[1][j]=0;
    }
  }


  ll ans=dp[0][0];
  ans=ans*fac[N-I.size()-O.size()+IO.size()]%mod;
  cout<<ans<<'\n';
}
accuracy: 1
time_ms: 70
memory_kb: 4096
final_rank: 8

code_snippet: #include <iostream>
using namespace std;

const long long mod = 1000000007;
int N, Sum, Sum2;
char c[10009]; int x[10009];
int depth[10009];

// Dynamic Programming
int ty[10009];
int dp[10009][5009];

int main() {
	// Input
	cin >> N;
	for (int i = 1; i <= 2 * N; i++) {
		cin >> c[i] >> x[i];
		if (c[i] == 'I' && x[i] != 0) ty[x[i]] |= 1;
		if (c[i] == 'O' && x[i] != 0) ty[x[i]] |= 2;
	}
	for (int i = 1; i <= N; i++) {
		if (ty[i] == 2) Sum += 1;
		if (ty[i] == 0 || ty[i] == 2) Sum2 += 1;
	}
	for (int i = 1; i <= 2 * N; i++) {
		depth[i] = depth[i - 1];
		if (ty[x[i]] == 3) continue;
		if (c[i] == 'I') depth[i] += 1;
		if (c[i] == 'O') depth[i] -= 1;
	}
	
	// Dynamic Programming
	int CountI = 0, CountD = 0;
	dp[0][0] = 1;
	for (int i = 0; i < 2 * N; i++) {
		for (int j = 0; j <= depth[i]; j++) {
			if (dp[i][j] == 0) continue;
			if (ty[x[i + 1]] == 3) {
				dp[i + 1][j] += dp[i][j];
				if (dp[i + 1][j] >= mod) dp[i + 1][j] -= mod;
				continue;
			}
			
			// In case 'I'
			if (c[i + 1] == 'I') {
				if (x[i + 1] != 0) {
					dp[i + 1][j] += dp[i][j];
					if (dp[i + 1][j] >= mod) dp[i + 1][j] -= mod;
				}
				if (x[i + 1] == 0) {
					int Rem_Total = Sum2 - CountI;
					int Rem_Decided = Sum - (CountD + j);
					
					// dp[i][j] -> dp[i+1][j]
					if (Rem_Total - Rem_Decided >= 1) {
						dp[i + 1][j] += (1LL * (Rem_Total - Rem_Decided) * dp[i][j]) % mod;
						if (dp[i + 1][j] >= mod) dp[i + 1][j] -= mod;
					}
					
					// dp[i][j] -> dp[i+1][j+1]
					if (Rem_Decided >= 1) {
						dp[i + 1][j + 1] += dp[i][j];
						if (dp[i + 1][j + 1] >= mod) dp[i + 1][j + 1] -= mod;
					}
				}
			}
			
			// In case 'O'
			if (c[i + 1] == 'O') {
				int rem = depth[i] - j;
				if (x[i + 1] != 0 && j >= 1) {
					dp[i + 1][j - 1] += (1LL * j * dp[i][j]) % mod;
					if (dp[i + 1][j - 1] >= mod) dp[i + 1][j - 1] -= mod;
				}
				if (x[i + 1] == 0 && rem >= 1) {
					dp[i + 1][j] += (1LL * rem * dp[i][j]) % mod;
					if (dp[i + 1][j] >= mod) dp[i + 1][j] -= mod;
				}
			}
		}
		if (c[i + 1] == 'I' && (ty[x[i+1]] == 0 || ty[x[i+1]] == 2)) CountI += 1;
		if (c[i + 1] == 'O' && ty[x[i+1]] == 2) CountD += 1;
	}
	
	/*cout << "DP:" << endl;
	for (int i = 0; i <= 2 * N; i++) {
		for (int j = 0; j <= depth[i]; j++) cout << dp[i][j] << " ";
		cout << endl;
	}*/
	
	// Output
	cout << dp[2 * N][0] << endl;
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 196736
final_rank: 17

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; --i)
#define all(c) std::begin(c), std::end(c);

#ifdef LOCAL
#define debug(...) debug_impl(#__VA_ARGS__, __VA_ARGS__)
template <class T, class ... Args> void debug_impl(string s, T&& first, Args &&...args) {
    string opn = sizeof...(args) == 0 ? "" : "(";
    string cls = sizeof...(args) == 0 ? "" : ")";
    cerr << "[\033[32mDEBUG\033[m] " << opn << s << cls << ": " << opn << forward<T>(first);
    ((cerr << ", " << forward<Args>(args)), ..., (cerr << cls << '\n'));
}
#else
#define debug(...) void(0)
#endif

template <typename T> bool chmax(T& a, const T& b) { return b > a ? (a = b, true) : false; }
template <typename T> bool chmin(T& a, const T& b) { return b < a ? (a = b, true) : false; }

template <class T> istream& operator>>(istream& in, vector<T>& v) {
    for (auto& e : v) in >> e;
    return in;
}
template <class ...Args> void read(Args &...args) {
    (cin >> ... >> args);
}
template <class T> ostream& operator<<(ostream& out, const vector<T>& v) {
    int n = v.size();
    rep(i, n) {
        out << v[i];
        if (i + 1 != n) out << ' ';
    }
    return out;
}
template <class H, class ...T> void print(H&& h, T &&...t) {
    cout << h, ((cout << ' ' << forward<T>(t)), ..., (cout << '\n'));
}

template <int MOD>
struct modint {
    static constexpr int mod = MOD;
    unsigned x;
    modint() : x(0) {}
    modint(long long sig) {
        int sigt = sig % mod;
        if (sigt < 0) sigt += mod;
        x = sigt;
    }
    int val() const {
        return x;
    }
    friend modint& operator+=(modint& x, const modint& y) {
        x.x += y.x;
        if (x.x >= mod) x.x -= mod;
        return x;
    }
    friend modint& operator-=(modint& x, const modint& y) {
        x.x -= y.x;
        if (x.x < 0) x.x += mod;
        return x;
    }
    friend modint& operator*=(modint& x, const modint& y) {
        x.x = (unsigned long long) x.x * y.x % mod;
        return x;
    }
    friend modint operator+(modint x, const modint& y) {
        return x += y;
    }
    friend modint operator-(modint x, const modint& y) {
        return x -= y;
    }
    friend modint operator*(modint x, const modint& y) {
        return x *= y;
    }
};

using mint = modint<1000000007>;

void solve(vector<char> op, vector<int> id) {
    const int n = op.size() / 2;

    vector<int> cnt(2 * n + 1);
    rep(i, 2 * n) {
        cnt[i + 1] = cnt[i] + (op[i] == 'I');
    }

    int t = n;
    for (int x : id) {
        if (x >= 0) --t;
    }

    vector<mint> pd(n + 1);
    pd[0] = 1;

    rep(i, 2 * n) {
        vector<mint> dp(n + 1);
        rep(j, n + 1) if (pd[j].val()) {
            const int k = 2 * cnt[i] - i - j;
            if (op[i] == 'I') {
                if (id[i] >= 0) {
                    dp[j] += pd[j];
                } else if (j + 1 <= n) {
                    dp[j + 1] += pd[j];
                }
            } else {
                if (id[i] >= 0) {
                    if (j) {
                        dp[j - 1] += pd[j] * j;
                    }
                } else {
                    dp[j] += pd[j] * k;
                    if (j) {
                        dp[j - 1] += pd[j] * j;
                    }
                }
            }
        }
        pd.swap(dp);
    }
    mint ans = pd[0];
    rep(v, t) ans *= t - v;
    print(ans.val());
}

int main() {
    int n;
    read(n);

    set<int> din, dout;

    vector<char> op(2 * n);
    vector<int> id(2 * n);
    rep(i, 2 * n) {
        char c;
        cin >> c;
        int v;
        cin >> v;
        --v;
        op[i] = c;
        id[i] = v;

        if (c == 'I' and v >= 0) {
            din.insert(v);
        }
        if (c == 'O' and v >= 0) {
            if (din.count(v)) {
                dout.insert(v);
            }
        }
    }

    vector<char> op2;
    vector<int> id2;

    rep(i, 2 * n) {
        if (not dout.count(id[i])) {
            op2.push_back(op[i]);
            id2.push_back(id[i]);
        }
    }

    // debug(op2);
    // debug(id2);

    solve(op2, id2);
}
accuracy: 1
time_ms: 50
memory_kb: 3880
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <array>
#include <algorithm>
#include <numeric>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <cassert>
#include <iterator>
#include <random>


constexpr int MOD = 1'000'000'007;
int main() {
	int n; std::cin >> n;
	std::vector<std::pair<bool, int>> infos(2 * n);
	for (auto& [in, id] : infos) {
		char t; std::cin >> t >> id; --id;
		in = t == 'I';
	}
	std::vector<bool> has_in(n, false), has_out(n, false);
	for (const auto [in, id] : infos) {
		if (id >= 0) {
			if (in) {
				has_in[id] = true;
			}
			else {
				has_out[id] = true;
			}
		}
	}
	std::vector<long long int> memo(n + 1, 0); memo[0] = 1;
	int in_rest{ 0 };
	for (const auto [in, id]: infos) {
		if (id >= 0 && has_in[id] && has_out[id]) continue;
		if (in) {
			++in_rest;
			if (id == -1) {
				for (auto i = in_rest; i > 0; --i) {
					memo[i] = memo[i - 1];
				}
				memo[0] = 0;
			}
		}
		else {
			if (id == -1) {
				for (auto i = 0; i < in_rest; ++i) {
					memo[i] = ((i + 1) * memo[i + 1] + (in_rest - i) * memo[i]) % MOD;
				}
				memo[in_rest] = 0;
			}
			else {
				for (auto i = 0; i < in_rest; ++i) {
					memo[i] = (i + 1) * memo[i + 1] % MOD;
				}
				memo[in_rest] = 0;
			}
			--in_rest;
		}
	}
	auto result = memo[0];
	int free_count{ 0 };
	for (auto i = 0; i < n; ++i) {
		if (has_in[i] || has_out[i]) continue;
		result = result * ++free_count % MOD;
	}
	std::cout << result << '\n';
}
accuracy: 1
time_ms: 10
memory_kb: 3552
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#pragma region Header
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
using f64 = double;
using f80 = long double;
using f128 = __float128;
constexpr i32 operator"" _i32(u64 v)
{
    return v;
}
constexpr i32 operator"" _u32(u64 v)
{
    return v;
}
constexpr i64 operator"" _i64(u64 v)
{
    return v;
}
constexpr u64 operator"" _u64(u64 v)
{
    return v;
}
constexpr f64 operator"" _f64(f80 v)
{
    return v;
}
constexpr f80 operator"" _f80(f80 v)
{
    return v;
}
using Istream = std::istream;
using Ostream = std::ostream;
using Str = std::string;
template<typename T>
using Lt = std::less<T>;
template<typename T>
using Gt = std::greater<T>;
template<typename T>
using IList = std::initializer_list<T>;
template<int n>
using BSet = std::bitset<n>;
template<typename T1, typename T2>
using Pair = std::pair<T1, T2>;
template<typename... Ts>
using Tup = std::tuple<Ts...>;
template<typename T, int N>
using Arr = std::array<T, N>;
template<typename... Ts>
using Deq = std::deque<Ts...>;
template<typename... Ts>
using Set = std::set<Ts...>;
template<typename... Ts>
using MSet = std::multiset<Ts...>;
template<typename... Ts>
using USet = std::unordered_set<Ts...>;
template<typename... Ts>
using UMSet = std::unordered_multiset<Ts...>;
template<typename... Ts>
using Map = std::map<Ts...>;
template<typename... Ts>
using MMap = std::multimap<Ts...>;
template<typename... Ts>
using UMap = std::unordered_map<Ts...>;
template<typename... Ts>
using UMMap = std::unordered_multimap<Ts...>;
template<typename... Ts>
using Vec = std::vector<Ts...>;
template<typename... Ts>
using Stack = std::stack<Ts...>;
template<typename... Ts>
using Queue = std::queue<Ts...>;
template<typename T>
using MaxHeap = std::priority_queue<T>;
template<typename T>
using MinHeap = std::priority_queue<T, Vec<T>, Gt<T>>;
using NSec = std::chrono::nanoseconds;
using USec = std::chrono::microseconds;
using MSec = std::chrono::milliseconds;
using Sec = std::chrono::seconds;
template<typename T>
constexpr T LIMMIN = std::numeric_limits<T>::min();
template<typename T>
constexpr T LIMMAX = std::numeric_limits<T>::max();
template<typename T>
constexpr T INF = (LIMMAX<T> - 1) / 2;
template<typename T>
constexpr T PI = T{3.141592653589793238462643383279502884};
template<typename T = u64>
constexpr T TEN(const int n)
{
    return n == 0 ? T{1} : TEN<T>(n - 1) * T{10};
}
Ostream& operator<<(Ostream& os, i128 v)
{
    bool minus = false;
    if (v < 0) { minus = true, v = -v; }
    Str ans;
    if (v == 0) { ans = "0"; }
    while (v) {
        ans.push_back('0' + v % 10), v /= 10;
    }
    std::reverse(ans.begin(), ans.end());
    return os << (minus ? "-" : "") << ans;
}
Ostream& operator<<(Ostream& os, u128 v)
{
    Str ans;
    if (v == 0) { ans = "0"; }
    while (v) {
        ans.push_back('0' + v % 10), v /= 10;
    }
    std::reverse(ans.begin(), ans.end());
    return os << ans;
}
template<typename T>
bool chmin(T& a, const T& b)
{
    if (a > b) {
        a = b;
        return true;
    } else {
        return false;
    }
}
template<typename T>
bool chmax(T& a, const T& b)
{
    if (a < b) {
        a = b;
        return true;
    } else {
        return false;
    }
}
template<typename T>
constexpr T floorDiv(T x, T y)
{
    if (y < T{}) { x = -x, y = -y; }
    return x >= T{} ? x / y : (x - y + 1) / y;
}
template<typename T>
constexpr T ceilDiv(T x, T y)
{
    if (y < T{}) { x = -x, y = -y; }
    return x >= T{} ? (x + y - 1) / y : x / y;
}
template<typename T, typename I>
constexpr T modPower(T v, I n, T mod)
{
    T ans = 1 % mod;
    for (; n > 0; n >>= 1, (v *= v) %= mod) {
        if (n % 2 == 1) { (ans *= v) %= mod; }
    }
    return ans;
}
template<typename T, typename I>
constexpr T power(T v, I n)
{
    T ans = 1;
    for (; n > 0; n >>= 1, v *= v) {
        if (n % 2 == 1) { ans *= v; }
    }
    return ans;
}
template<typename T, typename I>
constexpr T power(T v, I n, const T& e)
{
    T ans = e;
    for (; n > 0; n >>= 1, v *= v) {
        if (n % 2 == 1) { ans *= v; }
    }
    return ans;
}
template<typename T>
Vec<T> operator+=(Vec<T>& vs1, const Vec<T>& vs2)
{
    vs1.insert(vs1.end(), vs2.begin(), vs2.end());
    return vs1;
}
template<typename T>
Vec<T> operator+(const Vec<T>& vs1, const Vec<T>& vs2)
{
    auto vs = vs1;
    vs += vs2;
    return vs;
}
template<typename Vs, typename V>
void fillAll(Vs& arr, const V& v)
{
    if constexpr (std::is_convertible<V, Vs>::value) {
        arr = v;
    } else {
        for (auto& subarr : arr) {
            fillAll(subarr, v);
        }
    }
}
template<typename Vs>
void sortAll(Vs& vs)
{
    std::sort(std::begin(vs), std::end(vs));
}
template<typename Vs, typename C>
void sortAll(Vs& vs, C comp)
{
    std::sort(std::begin(vs), std::end(vs), comp);
}
template<typename Vs>
void reverseAll(Vs& vs)
{
    std::reverse(std::begin(vs), std::end(vs));
}
template<typename V, typename Vs>
V sumAll(const Vs& vs)
{
    if constexpr (std::is_convertible<Vs, V>::value) {
        return static_cast<V>(vs);
    } else {
        V ans = 0;
        for (const auto& v : vs) {
            ans += sumAll<V>(v);
        }
        return ans;
    }
}
template<typename Vs>
int minInd(const Vs& vs)
{
    return std::min_element(std::begin(vs), std::end(vs)) - std::begin(vs);
}
template<typename Vs>
int maxInd(const Vs& vs)
{
    return std::max_element(std::begin(vs), std::end(vs)) - std::begin(vs);
}
template<typename Vs, typename V>
int lbInd(const Vs& vs, const V& v)
{
    return std::lower_bound(std::begin(vs), std::end(vs), v) - std::begin(vs);
}
template<typename Vs, typename V>
int ubInd(const Vs& vs, const V& v)
{
    return std::upper_bound(std::begin(vs), std::end(vs), v) - std::begin(vs);
}
template<typename T, typename F>
Vec<T> genVec(int n, F gen)
{
    Vec<T> ans;
    std::generate_n(std::back_insert_iterator(ans), n, gen);
    return ans;
}
Vec<int> iotaVec(int n, int offset = 0)
{
    Vec<int> ans(n);
    std::iota(ans.begin(), ans.end(), offset);
    return ans;
}
constexpr int popcount(const u64 v)
{
    return v ? __builtin_popcountll(v) : 0;
}
constexpr int log2p1(const u64 v)
{
    return v ? 64 - __builtin_clzll(v) : 0;
}
constexpr int lsbp1(const u64 v)
{
    return __builtin_ffsll(v);
}
constexpr int clog(const u64 v)
{
    return v ? log2p1(v - 1) : 0;
}
constexpr u64 ceil2(const u64 v)
{
    const int l = clog(v);
    return (l == 64) ? 0_u64 : (1_u64 << l);
}
constexpr u64 floor2(const u64 v)
{
    return v ? (1_u64 << (log2p1(v) - 1)) : 0_u64;
}
constexpr bool ispow2(const u64 v)
{
    return (v > 0) and ((v & (v - 1)) == 0);
}
constexpr bool btest(const u64 mask, const int ind)
{
    return (mask >> ind) & 1_u64;
}
template<typename F>
struct Fix : F
{
    Fix(F&& f) : F{std::forward<F>(f)} {}
    template<typename... Args>
    auto operator()(Args&&... args) const
    {
        return F::operator()(*this, std::forward<Args>(args)...);
    }
};
class irange
{
private:
    struct itr
    {
        itr(i64 start = 0, i64 step = 1) : m_cnt{start}, m_step{step} {}
        bool operator!=(const itr& it) const
        {
            return m_cnt != it.m_cnt;
        }
        int operator*()
        {
            return m_cnt;
        }
        itr& operator++()
        {
            m_cnt += m_step;
            return *this;
        }
        i64 m_cnt, m_step;
    };
    i64 m_start, m_end, m_step;
public:
    irange(i64 start, i64 end, i64 step = 1)
    {
        assert(step != 0);
        const i64 d = std::abs(step);
        const i64 l = (step > 0 ? start : end);
        const i64 r = (step > 0 ? end : start);
        int n = (r - l) / d + ((r - l) % d ? 1 : 0);
        if (l >= r) { n = 0; }
        m_start = start;
        m_end = start + step * n;
        m_step = step;
    }
    itr begin() const
    {
        return itr{m_start, m_step};
    }
    itr end() const
    {
        return itr{m_end, m_step};
    }
};
irange rep(int end)
{
    return irange(0, end, 1);
}
irange per(int rend)
{
    return irange(rend - 1, -1, -1);
}
#pragma COMMENT("[REFS] Xoshiro: https://prng.di.unimi.it")
namespace xoshiro_impl {
u64 x;
u64 next()
{
    uint64_t z = (x += 0x9e3779b97f4a7c15);
    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
    z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
    return z ^ (z >> 31);
}
} // namespace xoshiro_impl
class Xoshiro32
{
public:
    using result_type = u32;
    using T = result_type;
    Xoshiro32(T seed = 0)
    {
        xoshiro_impl::x = seed;
        s[0] = xoshiro_impl::next();
        s[1] = xoshiro_impl::next();
        s[2] = xoshiro_impl::next();
        s[3] = xoshiro_impl::next();
    }
    static constexpr T min()
    {
        return LIMMIN<T>;
    }
    static constexpr T max()
    {
        return LIMMAX<T>;
    }
    T operator()()
    {
        return next();
    }
private:
    static constexpr T rotl(const T x, int k)
    {
        return (x << k) | (x >> (32 - k));
    }
    T next()
    {
        const T ans = rotl(s[1] * 5, 7) * 9;
        const T t = s[1] << 9;
        s[2] ^= s[0];
        s[3] ^= s[1];
        s[1] ^= s[2];
        s[0] ^= s[3];
        s[2] ^= t;
        s[3] = rotl(s[3], 11);
        return ans;
    }
    T s[4];
};
class Xoshiro64
{
public:
    using result_type = u64;
    using T = result_type;
    Xoshiro64(T seed = 0)
    {
        xoshiro_impl::x = seed;
        s[0] = xoshiro_impl::next();
        s[1] = xoshiro_impl::next();
        s[2] = xoshiro_impl::next();
        s[3] = xoshiro_impl::next();
    }
    static constexpr T min()
    {
        return LIMMIN<T>;
    }
    static constexpr T max()
    {
        return LIMMAX<T>;
    }
    T operator()()
    {
        return next();
    }
private:
    static constexpr T rotl(const T x, int k)
    {
        return (x << k) | (x >> (64 - k));
    }
    T next()
    {
        const T ans = rotl(s[1] * 5, 7) * 9;
        const T t = s[1] << 17;
        s[2] ^= s[0];
        s[3] ^= s[1];
        s[1] ^= s[2];
        s[0] ^= s[3];
        s[2] ^= t;
        s[3] = rotl(s[3], 45);
        return ans;
    }
    T s[4];
};
template<typename Rng>
class RNG
{
public:
    using result_type = typename Rng::result_type;
    using T = result_type;
    static constexpr T min()
    {
        return Rng::min();
    }
    static constexpr T max()
    {
        return Rng::max();
    }
    RNG() : RNG(std::random_device{}()) {}
    RNG(T seed) : m_rng(seed) {}
    T operator()()
    {
        return m_rng();
    }
    template<typename T>
    T val(T min, T max)
    {
        return std::uniform_int_distribution<T>(min, max)(m_rng);
    }
    template<typename T>
    Pair<T, T> pair(T min, T max)
    {
        return std::minmax({val<T>(min, max), val<T>(min, max)});
    }
    template<typename T>
    Vec<T> vec(int n, T min, T max)
    {
        return genVec<T>(n, [&]() { return val<T>(min, max); });
    }
    template<typename T>
    Vec<Vec<T>> vvec(int n, int m, T min, T max)
    {
        return genVec<Vec<T>>(n, [&]() { return vec(m, min, max); });
    }
private:
    Rng m_rng;
};
RNG<std::mt19937> rng;
RNG<std::mt19937_64> rng64;
RNG<Xoshiro32> rng_xo;
RNG<Xoshiro64> rng_xo64;
class Scanner
{
public:
    Scanner(Istream& is = std::cin) : m_is{is}
    {
        m_is.tie(nullptr)->sync_with_stdio(false);
    }
    template<typename T>
    T val()
    {
        T v;
        return m_is >> v, v;
    }
    template<typename T>
    T val(T offset)
    {
        return val<T>() - offset;
    }
    template<typename T>
    Vec<T> vec(int n)
    {
        return genVec<T>(n, [&]() { return val<T>(); });
    }
    template<typename T>
    Vec<T> vec(int n, T offset)
    {
        return genVec<T>(n, [&]() { return val<T>(offset); });
    }
    template<typename T>
    Vec<Vec<T>> vvec(int n, int m)
    {
        return genVec<Vec<T>>(n, [&]() { return vec<T>(m); });
    }
    template<typename T>
    Vec<Vec<T>> vvec(int n, int m, const T offset)
    {
        return genVec<Vec<T>>(n, [&]() { return vec<T>(m, offset); });
    }
    template<typename... Args>
    auto tup()
    {
        return Tup<Args...>{val<Args>()...};
    }
    template<typename... Args>
    auto tup(const Args&... offsets)
    {
        return Tup<Args...>{val<Args>(offsets)...};
    }
private:
    Istream& m_is;
};
Scanner in;
class Printer
{
public:
    Printer(Ostream& os = std::cout) : m_os{os}
    {
        m_os << std::fixed << std::setprecision(15);
    }
    template<typename... Args>
    int operator()(const Args&... args)
    {
        dump(args...);
        return 0;
    }
    template<typename... Args>
    int ln(const Args&... args)
    {
        dump(args...), m_os << '\n';
        return 0;
    }
    template<typename... Args>
    int el(const Args&... args)
    {
        dump(args...), m_os << std::endl;
        return 0;
    }
private:
    template<typename T>
    void dump(const T& v)
    {
        m_os << v;
    }
    template<typename T>
    void dump(const Vec<T>& vs)
    {
        for (const int i : rep(vs.size())) {
            m_os << (i ? " " : ""), dump(vs[i]);
        }
    }
    template<typename T>
    void dump(const Vec<Vec<T>>& vss)
    {
        for (const int i : rep(vss.size())) {
            m_os << (i ? "\n" : ""), dump(vss[i]);
        }
    }
    template<typename T, typename... Ts>
    int dump(const T& v, const Ts&... args)
    {
        dump(v), m_os << ' ', dump(args...);
        return 0;
    }
    Ostream& m_os;
};
Printer out;
template<typename T, int n, int i = 0>
auto ndVec(int const (&szs)[n], const T x = T{})
{
    if constexpr (i == n) {
        return x;
    } else {
        return std::vector(szs[i], ndVec<T, n, i + 1>(szs, x));
    }
}
template<typename T, typename F>
T binSearch(T ng, T ok, F check)
{
    while (std::abs(ok - ng) > 1) {
        const T mid = (ok + ng) / 2;
        (check(mid) ? ok : ng) = mid;
    }
    return ok;
}
template<u32 mod_, u32 root_, u32 max2p_>
class modint
{
    template<typename U = u32&>
    static U modRef()
    {
        static u32 s_mod = 0;
        return s_mod;
    }
    template<typename U = u32&>
    static U rootRef()
    {
        static u32 s_root = 0;
        return s_root;
    }
    template<typename U = u32&>
    static U max2pRef()
    {
        static u32 s_max2p = 0;
        return s_max2p;
    }
public:
    template<typename U = const u32>
    static constexpr std::enable_if_t<mod_ != 0, U> mod()
    {
        return mod_;
    }
    template<typename U = const u32>
    static std::enable_if_t<mod_ == 0, U> mod()
    {
        return modRef();
    }
    template<typename U = const u32>
    static constexpr std::enable_if_t<mod_ != 0, U> root()
    {
        return root_;
    }
    template<typename U = const u32>
    static std::enable_if_t<mod_ == 0, U> root()
    {
        return rootRef();
    }
    template<typename U = const u32>
    static constexpr std::enable_if_t<mod_ != 0, U> max2p()
    {
        return max2p_;
    }
    template<typename U = const u32>
    static std::enable_if_t<mod_ == 0, U> max2p()
    {
        return max2pRef();
    }
    template<typename U = u32>
    static void setMod(std::enable_if_t<mod_ == 0, U> m)
    {
        modRef() = m;
    }
    template<typename U = u32>
    static void setRoot(std::enable_if_t<mod_ == 0, U> r)
    {
        rootRef() = r;
    }
    template<typename U = u32>
    static void setMax2p(std::enable_if_t<mod_ == 0, U> m)
    {
        max2pRef() = m;
    }
    constexpr modint() : m_val{0} {}
    constexpr modint(i64 v) : m_val{normll(v)} {}
    constexpr void setRaw(u32 v)
    {
        m_val = v;
    }
    constexpr modint operator-() const
    {
        return modint{0} - (*this);
    }
    constexpr modint& operator+=(const modint& m)
    {
        m_val = norm(m_val + m.val());
        return *this;
    }
    constexpr modint& operator-=(const modint& m)
    {
        m_val = norm(m_val + mod() - m.val());
        return *this;
    }
    constexpr modint& operator*=(const modint& m)
    {
        m_val = normll((i64)m_val * (i64)m.val() % (i64)mod());
        return *this;
    }
    constexpr modint& operator/=(const modint& m)
    {
        return *this *= m.inv();
    }
    constexpr modint operator+(const modint& m) const
    {
        auto v = *this;
        return v += m;
    }
    constexpr modint operator-(const modint& m) const
    {
        auto v = *this;
        return v -= m;
    }
    constexpr modint operator*(const modint& m) const
    {
        auto v = *this;
        return v *= m;
    }
    constexpr modint operator/(const modint& m) const
    {
        auto v = *this;
        return v /= m;
    }
    constexpr bool operator==(const modint& m) const
    {
        return m_val == m.val();
    }
    constexpr bool operator!=(const modint& m) const
    {
        return not(*this == m);
    }
    friend Istream& operator>>(Istream& is, modint& m)
    {
        i64 v;
        return is >> v, m = v, is;
    }
    friend Ostream& operator<<(Ostream& os, const modint& m)
    {
        return os << m.val();
    }
    constexpr u32 val() const
    {
        return m_val;
    }
    template<typename I>
    constexpr modint pow(I n) const
    {
        return power(*this, n);
    }
    constexpr modint inv() const
    {
        return pow(mod() - 2);
    }
    static modint sinv(u32 n)
    {
        static Vec<modint> is{1, 1};
        for (u32 i = (u32)is.size(); i <= n; i++) {
            is.push_back(-is[mod() % i] * (mod() / i));
        }
        return is[n];
    }
    static modint fact(u32 n)
    {
        static Vec<modint> fs{1, 1};
        for (u32 i = (u32)fs.size(); i <= n; i++) {
            fs.push_back(fs.back() * i);
        }
        return fs[n];
    }
    static modint ifact(u32 n)
    {
        static Vec<modint> ifs{1, 1};
        for (u32 i = (u32)ifs.size(); i <= n; i++) {
            ifs.push_back(ifs.back() * sinv(i));
        }
        return ifs[n];
    }
    static modint comb(int n, int k)
    {
        return k > n or k < 0 ? modint{0} : fact(n) * ifact(n - k) * ifact(k);
    }
private:
    static constexpr u32 norm(u32 x)
    {
        return x < mod() ? x : x - mod();
    }
    static constexpr u32 normll(i64 x)
    {
        return norm(u32(x % (i64)mod() + (i64)mod()));
    }
    u32 m_val;
};
using modint_1000000007 = modint<1000000007, 5, 1>;
using modint_998244353 = modint<998244353, 3, 23>;
template<int id>
using modint_dynamic = modint<0, 0, id>;
template<typename T = int>
class Graph
{
    struct Edge
    {
        Edge() = default;
        Edge(int i, int t, T c) : id{i}, to{t}, cost{c} {}
        int id;
        int to;
        T cost;
        operator int() const
        {
            return to;
        }
    };
public:
    Graph(int n) : m_v{n}, m_edges(n) {}
    void addEdge(int u, int v, bool bi = false)
    {
        assert(0 <= u and u < m_v);
        assert(0 <= v and v < m_v);
        m_edges[u].emplace_back(m_e, v, 1);
        if (bi) { m_edges[v].emplace_back(m_e, u, 1); }
        m_e++;
    }
    void addEdge(int u, int v, const T& c, bool bi = false)
    {
        assert(0 <= u and u < m_v);
        assert(0 <= v and v < m_v);
        m_edges[u].emplace_back(m_e, v, c);
        if (bi) { m_edges[v].emplace_back(m_e, u, c); }
        m_e++;
    }
    const Vec<Edge>& operator[](const int u) const
    {
        assert(0 <= u and u < m_v);
        return m_edges[u];
    }
    Vec<Edge>& operator[](const int u)
    {
        assert(0 <= u and u < m_v);
        return m_edges[u];
    }
    int v() const
    {
        return m_v;
    }
    int e() const
    {
        return m_e;
    }
    friend Ostream& operator<<(Ostream& os, const Graph& g)
    {
        for (int u : rep(g.v())) {
            for (const auto& [id, v, c] : g[u]) {
                os << "[" << id << "]: ";
                os << u << "->" << v << "(" << c << ")\n";
            }
        }
        return os;
    }
    Vec<T> sizes(int root = 0) const
    {
        const int N = v();
        assert(0 <= root and root < N);
        Vec<T> ss(N, 1);
        Fix([&](auto dfs, int u, int p) -> void {
            for (const auto& [id, v, c] : m_edges[u]) {
                static_cast<void>(id);
                if (v == p) { continue; }
                dfs(v, u);
                ss[u] += ss[v];
            }
        })(root, -1);
        return ss;
    }
    Vec<T> depths(int root = 0) const
    {
        const int N = v();
        assert(0 <= root and root < N);
        Vec<T> ds(N, 0);
        Fix([&](auto dfs, int u, int p) -> void {
            for (const auto& [id, v, c] : m_edges[u]) {
                static_cast<void>(id);
                if (v == p) { continue; }
                ds[v] = ds[u] + c;
                dfs(v, u);
            }
        })(root, -1);
        return ds;
    }
    Vec<int> parents(int root = 0) const
    {
        const int N = v();
        assert(0 <= root and root < N);
        Vec<int> ps(N, -1);
        Fix([&](auto dfs, int u, int p) -> void {
            for (const auto& [id, v, c] : m_edges[u]) {
                static_cast<void>(id);
                if (v == p) { continue; }
                ps[v] = u;
                dfs(v, u);
            }
        })(root, -1);
        return ps;
    }
private:
    int m_v;
    int m_e = 0;
    Vec<Vec<Edge>> m_edges;
};
#pragma endregion
int main()
{
    using mint = modint_1000000007;
    const auto N = in.val<int>();
    Vec<int> IOs(2 * N);
    Vec<int> xs(2 * N);
    Vec<int> masks(N + 1, 0);
    for (int i : rep(2 * N)) {
        IOs[i] = in.val<char>() == 'O';
        xs[i] = in.val<int>();
        if (xs[i] != 0) { masks[xs[i]] |= (1 << IOs[i]); }
    }
    for (int i : rep(2 * N)) {
        if (masks[xs[i]] == 3) { IOs[i] = -1; }
    }
    Vec<int> sums(2 * N + 1, 0);
    for (int i : rep(2 * N)) {
        if (IOs[i] == -1) {
            sums[i + 1] = sums[i];
        } else if (IOs[i] == 0) {
            sums[i + 1] = sums[i] + 1;
        } else {
            sums[i + 1] = sums[i] - 1;
        }
        assert(sums[i + 1] >= 0);
    }
    assert(sums[2 * N] == 0);
    Vec<mint> dp(N + 1, 0);
    dp[0] = 1;
    for (int i : rep(2 * N)) {
        Vec<mint> ndp(N + 1, 0);
        if (IOs[i] == -1) { continue; }
        if (IOs[i] == 1) {
            if (xs[i] == 0) {
                for (int j : rep(N + 1)) {
                    const int k = sums[i] - j;
                    if (k < 0) { continue; }
                    if (j >= 1) { ndp[j - 1] += dp[j] * j; }
                    if (k >= 1) { ndp[j] += dp[j] * k; }
                }
            } else {
                for (int j : rep(N + 1)) {
                    const int k = sums[i] - j;
                    if (k < 0) { continue; }
                    if (j >= 1) { ndp[j - 1] += dp[j] * j; }
                }
            }
        } else {
            if (xs[i] == 0) {
                for (int j : rep(N + 1)) {
                    const int k = sums[i] - j;
                    if (k < 0) { continue; }
                    ndp[j + 1] += dp[j];
                }
            } else {
                for (int j : rep(N + 1)) {
                    const int k = sums[i] - j;
                    if (k < 0) { continue; }
                    ndp[j] += dp[j];
                }
            }
        }
        std::swap(ndp, dp);
    }
    mint ans = dp[0];
    int n = 0;
    for (int i : irange(1, N + 1)) {
        if (masks[i] == 0) { n++; }
    }
    ans *= mint::fact(n);
    out.ln(ans);
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3692
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------


#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif


#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

// constexpr int MOD = 998244353;
constexpr int MOD = 1000000007;
using mint = atcoder::static_modint<MOD>;
ostream &operator<<(ostream &os, const mint &v) {
  return os << v.val();
}

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

void solve() {
  int n;
  cin >> n;
  vector<pair<char, int>> cx(2 * n);
  vector<int> cnt(n, 0);
  vector<int> h;
  int cur = 0;
  for (auto &[c, x] : cx) {
    cin >> c >> x;
    x--;
    if (x >= 0) cnt[x]++;
  }

  for (const auto [c, x] : cx) {
    if (x == -1 || cnt[x] != 2) {
      if (c == 'I')
        cur++;
      else
        cur--;
    }
    h.push_back(cur);
  }
  dmp(h);

  auto dp = vect(2 * n + 1, vect(n + 1, mint(0)));
  dp[0][0] = mint(1);
  for (int i = 0; i < 2 * n; i++) {
    auto [c, x] = cx[i];
    if (x != -1 && cnt[x] == 2) {
      dp[i + 1] = dp[i];
      continue;
    }
    for (int j = 0; j <= n; j++) {
      if (c == 'I') {
        if (x == -1) {
          dp[i + 1][j] += dp[i][j];
        } else {
          if (j + 1 <= n) dp[i + 1][j + 1] += dp[i][j];
        }
      } else {
        if (x == -1) {
          if (j > 0) dp[i + 1][j - 1] += dp[i][j] * j;
          dp[i + 1][j] += dp[i][j] * (h[i] + 1 - j);
        } else {
          dp[i + 1][j] += dp[i][j] * (h[i] + 1 - j);
        }
      }
    }
  }

  // rep(i, 2 * n + 1) {
  //   rep(j, n + 1) { cout << dp[i][j] << ' '; }
  //   cout << endl;
  // }

  mint ans = dp[2 * n][0];
  int tbd = std::count(all(cnt), 0);
  for (int i = 1; i <= tbd; i++) ans *= i;
  cout << ans << endl;

  return;
}

int main() {
  fastio();
  if (!multitest) {
    solve();
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 198964
final_rank: 19

code_snippet: #pragma GCC optimize("Ofast") 
#include <bits/stdc++.h>
using namespace std;
using ll = long long int ;
using ld = long double ;
using P = pair<ll,ll>;
using Graph= vector<vector<ll>>;
struct edge{ll to ; ll cost ;} ;
using graph =vector<vector<edge>> ;
#define rep(i,n) for (ll i=0; i < (n); ++i)
#define rep2(i,n,m) for(ll i=n;i<=m;i++)
#define rep3(i,n,m) for(ll i=n;i>=m;i--)
#define pb push_back 
#define eb emplace_back 
#define ppb pop_back 
#define mpa make_pair 
#define fi first  
#define se second  
#define set20 cout<<fixed<<setprecision(20)  ;
const ll INF=1e18 ;   
inline void chmax(ll& a,ll b){a=max(a,b);}  
inline void chmin(ll& a,ll b){a=min(a,b);} 
long double pi=acos(-1) ;  
ll gcd(ll a, ll b) { return b?gcd(b,a%b):a;}  
ll lcm(ll a, ll b) { return a/gcd(a,b)*b;} 
ll dx[4] {1,0,-1,0} ;
ll dy[4] {0,1,0,-1} ;
#define debug cout<<888<<endl ;

// ミント
//int mod ;  //任意modではconst外す

const int mod =1e9+7 ;//924844033;  
  //998244353;

struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  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 *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }
 
  // for prime mod
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}
//昆布

struct combination {
  vector<mint> fact, ifact;
  combination(int n):fact(n+1),ifact(n+1) {
    assert(n < mod); //任意modではここ消すcombmain内に
    fact[0] = 1;
    for (int i = 1; i <= n; ++i) fact[i] = fact[i-1]*i;
    ifact[n] = fact[n].inv();
    for (int i = n; i >= 1; --i) ifact[i-1] = ifact[i]*i;
  }
  mint operator()(int n, int k) {
    if (k < 0 || k > n) return 0;
    return fact[n]*ifact[k]*ifact[n-k];
  }
  mint p(int n,int k){
    return fact[n]*ifact[n-k] ; //kは個数
  }
  }  c(6005)
  ;


mint modpow(ll a,ll b){
 if(b==0) return 1 ;
 mint c= modpow(a,b/2) ;
 if(b%2==1) return c*c*a ;
 else return c*c ;
}

mint mmodpow(mint a,ll b){
  if(b==0) return 1ll ;
  mint c=mmodpow(a,(b/2)) ;
  if(b%2==1) return c*c*a ;
  else return c*c ;
}
mint komb(ll n,ll m){
  mint x=1 ;mint y=1 ;
  rep(i,m){
    x*= n-i ;
    y*= i+1 ;
  }
  return x/y ;
}
 
 map<ll,ll> factor(ll n){  //素因数とオーダーをマップで管理
  map <ll,ll> ord ;  
  for(ll i=2;i*i<=n;i++){
        if(n%i==0){
            int res=0;
            while(n%i==0){
                n/=i;
                res++;
            }
            ord[i]=res;
        }
    }
    if(n!=1) ord[n]++;
    return ord ;
 }

struct UnionFind {
  vector<int> d;
  UnionFind(int n=0): d(n,-1) {}
  int find(int x) {
    if (d[x] < 0) return x;
    return d[x] = find(d[x]);
  }
  bool unite(int x, int y) {
    x = find(x); y = find(y);
    if (x == y) return false;
    if (d[x] > d[y]) swap(x,y);
    d[x] += d[y];
    d[y] = x;
    return true;
  }
  bool same(int x, int y) { return find(x) == find(y);}
  int size(int x) { return -d[find(x)];}
};

// sum(x) x以下の和
// sum(a,b) a以上b以下の和
template<typename T>
struct BIT {
  int n;
  vector<T> d;
  BIT(int n=0):n(n),d(n+1) {}
  void add(int i, T x=1) {  //x=1ならsumは個数のカウント
    for (i++; i <= n; i += i&-i) {
      d[i] += x;
    }
  }
  T sum(int i) {
    T x = 0;
    for (i++; i; i -= i&-i) {
      x += d[i];
    }
    return x;
  }
  T sum(int i,int j) {
    if(i>0) return sum(j)-sum(i-1);
    else return sum(j) ; } 
};

void dfs(ll s,ll t,Graph &g,vector<ll> &d){
  for(auto u:g[t]){
    if(u==s) continue;
    d[u]=d[t]+1;
  }
}

mint dp[5005];
mint ep[5005];


int main(){
  ios::sync_with_stdio(false) ;
  cin.tie(nullptr) ;
  
  ll n; cin>>n;
  ll m=1e9+7;

  vector<pair<char,ll>> A(2*n);

  vector<ll> cnt(n+1);

  rep(i,2*n){
    cin>>A[i].fi>>A[i].se;
    cnt[A[i].se]++;
  }
  

  dp[0]=1ll; //番号つき
  ll now=0ll;
  
  rep(i,2*n){
    if(cnt[A[i].se]==2){
      //rep(j,5005) ep[j]=dp[j];
      continue;
    }

    if(A[i].fi=='I'){
      if(A[i].se>0) rep(j,5004) ep[j+1]=dp[j];
      else rep(j,5005) ep[j]=dp[j];
      now++;
    }
    else{
      if(A[i].se>0){
        rep(j,5005){
          ep[j]+=dp[j]*(now-j);
        }
      }
      else{
        rep(j,5005){
          if(j>0) ep[j-1]+=dp[j]*j;
          ep[j]+=dp[j]*(now-j);
        }
      }
      now--;
    }

    rep(j,5005) dp[j]=ep[j];
    rep(j,5005) ep[j]=0ll;

  }
  
  ll sum=0ll;

  rep2(i,1,n){
    if(cnt[i]==0) sum++;
  }
  
  mint ans=dp[0];

  rep2(i,1,sum) ans*=i;

  cout<<ans<<endl;

  return 0 ;
}
accuracy: 1
time_ms: 120
memory_kb: 3740
final_rank: 14

code_snippet: #pragma GCC optimize("Ofast")
//#pragma GCC target ("sse4")

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 18;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

modint dp[5001];
modint cop[5001];
void solve() {
	int n; cin >> n;
	vector<char> c(2 * n);
	vector<int> id(2 * n);
	rep(i, 2 * n) {
		cin >> c[i] >> id[i];
	}
	vector<int> ste(n + 1);
	rep(i, 2 * n) {
		if (c[i] == 'I')ste[id[i]] |= 1;
		else ste[id[i]] |= 2;
	}
	int x = 0;
	rep1(i, n)if (ste[i] == 0)x++;
	dp[0] = 1;
	vector<int> le(2 * n + 1);
	vector<int> ri(2 * n + 1);
	vector<int> cl(2 * n + 1);
	vector<int> cr(2 * n + 1);
	rep(i, 2 * n) {
		le[i + 1] += le[i];
		ri[i + 1] += ri[i];
		cl[i + 1] += cl[i];
		cr[i + 1] += cr[i];
		if (id[i] == 0) {
			if (c[i] == 'I')cl[i + 1]++;
			else cr[i + 1]++;
		}
		else {
			if (c[i] == 'I') {
				if (ste[id[i]] == 1) {
					le[i + 1]++;
				}
			}
			else {
				if (ste[id[i]] == 2) {
					ri[i + 1]++;
				}
			}
		}
	}

	rep(i, 2 * n) {
		if (id[i] > 0) {
			if (ste[id[i]] == 2) {
				rep(j, x + 1)cop[j] = 0;
				rep(j, x + 1) {
					int num = cl[i] - j - ri[i];
					if (num > 0) {
						cop[j] += (modint)num * dp[j];
					}
				}
				rep(j, x + 1)dp[j] = cop[j];
			}
			continue;
		}
		rep(j, x + 1)cop[j] = 0;
		rep(j, x + 1) {
			if (dp[j] == (modint)0)continue;
			if (c[i] == 'I') {
				//use ?
				if (j < x) {
					cop[j + 1] += (modint)(x - j) * dp[j];
				}
				//not use ?
				cop[j] += dp[j];
				/*if (cl[i] >= j) {
					int num = (ri[2 * n] - ri[i]) - (cl[i] - j);
					if (num > 0) {
						cop[j] += (modint)num * dp[j];
					}
				}*/
			}
			else {
				int num = le[i] + j - cr[i];
				if (num > 0) {
					cop[j] += (modint)num * dp[j];
				}
			}
		}
		rep(j, x + 1)dp[j] = cop[j];
		/*rep(j, x + 1) {
			cout << i << " " << j << " "<<dp[j] << "\n";
		}*/
	}
	cout << dp[x] << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();

	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 7748
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=1167167167167167167;
const int INF=2100000000;
const ll mod=1e9+7;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}



void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int N;
	cin>>N;
	vector<char> C(N*2);
	vector<int> p(N*2),X(N);
	rep(i,N*2){
		cin>>C[i]>>p[i];
		p[i]--;
		if(p[i]!=-1) X[p[i]]++;
	}
	vector<ll> dp(1,1);
	ll S=0;
	rep(i,N*2){
		if(p[i]!=-1&&X[p[i]]==2) continue;
		if(C[i]=='I'){
			dp.push_back(0);
			S++;
			if(p[i]!=-1){
				for(int j=S;j>0;j--) swap(dp[j],dp[j-1]);
			}
		}else{
			vector<ll> n_dp(S);
			if(p[i]!=-1){
				rep(i,S){
					n_dp[i]=(dp[i]*(S-i))%mod;
				}
			}else{
				rep(i,S){
					n_dp[i]=(dp[i+1]*(i+1))%mod;
					n_dp[i]=(n_dp[i]+(dp[i]*(S-i))%mod)%mod;
				}
			}
			S--;
			swap(dp,n_dp);
		}
	}
	ll A=1;
	//cout<<dp[0]<<endl;
	rep(i,N){
		if(X[i]==0){
			dp[0]=(dp[0]*A)%mod;
			A++;
		}
	}
	cout<<dp[0]<<"\n";
}
accuracy: 1
time_ms: 60
memory_kb: 3624
final_rank: 5