Problem p03357 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <complex>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <valarray>
#include <vector>

#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <chrono>
#include <random>
#include <thread>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define all(c) c.begin(), c.end()
#define repeat(i, n) for (int i = 0; i < static_cast<int>(n); i++)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define NDEBUG
#define dump(x)
#endif

typedef complex<double> point;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "{";
  for (auto it = v.begin(); it != v.end(); ++it) {
    if (it != v.begin())
      os << ",";
    os << *it;
  }
  return os << "}";
}

using ll = int64_t;

struct Ball {
  char color;
  int number;
};

class BIT {
public:
  BIT(int n);
  int query(int i);
  void modify(int i, int v);

private:
  int size() { return m_size; }
  int m_size;
  vector<int> m_data;
};

BIT::BIT(int n) : m_size(n) {
  int len = 1;
  while (len < n + 1)
    len *= 2;
  m_data = vector<int>(len);
}

// 0-index
int BIT::query(int i) {
  i = i + 1;
  assert(1 <= i && i <= m_size);
  int ret = 0;
  while (i > 0) {
    ret += m_data[i];
    // 一番下の立っている bit を削除
    i -= i & -i;
  }
  return ret;
}

// 0-index
void BIT::modify(int i, int v) {
  i = i + 1;
  assert(1 <= i && i <= m_size);
  while (i <= m_size) {
    m_data[i] += v;
    i += i & -i;
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n;
  cin >> n;
  vector<Ball> ps;
  vector<int> whitePos(n);
  vector<int> blackPos(n);

  for (int i = 0; i < 2 * n; i++) {
    char c;
    int a;
    cin >> c >> a;
    a--; // 0-origin
    ps.push_back(Ball{c, a});

    if (c == 'W')
      whitePos[a] = i;
    else
      blackPos[a] = i;
  }

  const auto where = [&](const Ball &b) {
    if (b.color == 'W')
      return whitePos[b.number];
    else
      return blackPos[b.number];
  };

  // -----------------------------------------------------------
  vector<vector<int>> costw(n + 1, vector<int>(n + 1));
  for (int i = 0; i <= n; i++) {
    // i 個白
    BIT tree(2 * n);
    for (int j = 0; j < i; j++)
      tree.modify(where(Ball{'B', j}), 1);

    for (int j = 0; j < n; j++) {
      int k = where(Ball({'W', j}));

      costw[j][i] = k - tree.query(k);
      tree.modify(k, 1);
    }
  }
  // -----------------------------------------------------------
  vector<vector<int>> costb(n + 1, vector<int>(n + 1));
  for (int i = 0; i <= n; i++) {
    // i 個黒
    BIT tree(2 * n);
    for (int j = 0; j < i; j++)
      tree.modify(where(Ball{'W', j}), 1);

    for (int j = 0; j < n; j++) {
      int k = where(Ball({'B', j}));

      costb[i][j] = k - tree.query(k);
      tree.modify(k, 1);
    }
  }

  vector<vector<int>> dp(n + 1, vector<int>(n + 1));
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      if (i == 0 && j == 0)
        continue;

      int useWhite = (i == 0) ? 1000000000 : (dp[i - 1][j] + costw[i - 1][j]);
      int useBlack = (j == 0) ? 1000000000 : (dp[i][j - 1] + costb[i][j - 1]);

      dp[i][j] = min(useWhite, useBlack);
    }
  }
  cout << dp[n][n] << endl;

  cerr << "costw" << endl;
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      cerr << costw[i][j] << ",";
    }
    cerr << endl;
  }
  cerr << "costb" << endl;
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      cerr << costb[i][j] << ",";
    }
    cerr << endl;
  }

  cerr << "DP" << endl;
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      cerr << dp[i][j] << ",";
    }
    cerr << endl;
  }

  // int white = 0;
  // int black = 0;

  // int ret = 0;

  // vector<Ball> shouldbe(2*n);
  // {
  //     int white = n - 1;
  //     int black = n - 1;
  //     for (int i = 2*n-1; i >= 0; i--) {
  //         int wp = -1;
  //         int bp = -1;
  //         for (int j = 0; j < 2 * n; j++) {
  //             if (ps[j].number == black && ps[j].color == 'B')
  //                 bp = j;
  //             if (ps[j].number == white && ps[j].color == 'W')
  //                 wp = j;
  //         }
  //         int s = max(bp, wp);
  //         shouldbe[i].color = (s == bp) ? 'B' : 'W';
  //         shouldbe[i].number = (s == bp) ? black : white;
  //         if (s == bp)
  //             black--;
  //         else
  //             white--;
  //     }
  // }
  // for (int i = 0; i < 2 * n; i++){
  //      cerr << "(" << shouldbe[i].color << "," << shouldbe[i].number << ")"
  //      << " ";
  // }
  // cerr << endl;

  // for (int i = 0; i < 2 * n; i++){
  //     int s = 0;
  //     for (int j = 0; j < 2 * n; j++) {
  //         if(ps[j].color == shouldbe[i].color && ps[j].number ==
  //         shouldbe[i].number)
  //             s = j;
  //     }
  //     for (int j = s; j >= i + 1; j--) {
  //        swap(ps[j - 1], ps[j]);
  //        ret++;
  //     }
  // }

  // for (int i = 0; i < 2 * n; i++) {
  //     int wp = 4 * n;
  //     int bp = 4 * n;
  //     for (int j = 0; j < 2 * n; j++) {
  //         if (ps[j].number == black && ps[j].color == 'B')
  //             bp = j;
  //             if (ps[j].number == white && ps[j].color == 'W')
  //                 wp = j;
  //         }
  //         int s = (bp < wp) ? bp : wp;
  //         for (int j = s; j >= i + 1; j--) {
  //             swap(ps[j - 1], ps[j]);
  //             ret++;
  //         }
  //         if (bp < wp)
  //             black++;
  //         else
  //             white++;
  //     }
  // for (int i = 0; i < 2 * n; i++){
  //     cerr << "(" << ps[i].color << "," << ps[i].number << ")" << " ";
  // }
  // cerr << endl;
  // cout << ret << endl;
  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <complex>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <valarray>
#include <vector>

#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <chrono>
#include <random>
#include <thread>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define all(c) c.begin(), c.end()
#define repeat(i, n) for (int i = 0; i < static_cast<int>(n); i++)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define NDEBUG
#define dump(x)
#endif

typedef complex<double> point;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "{";
  for (auto it = v.begin(); it != v.end(); ++it) {
    if (it != v.begin())
      os << ",";
    os << *it;
  }
  return os << "}";
}

using ll = int64_t;

struct Ball {
  char color;
  int number;
};

class BIT {
public:
  BIT(int n);
  int query(int i);
  void modify(int i, int v);

private:
  int size() { return m_size; }
  int m_size;
  vector<int> m_data;
};

BIT::BIT(int n) : m_size(n) {
  int len = 1;
  while (len < n + 1)
    len *= 2;
  m_data = vector<int>(len);
}

// 0-index
int BIT::query(int i) {
  i = i + 1;
  assert(1 <= i && i <= m_size);
  int ret = 0;
  while (i > 0) {
    ret += m_data[i];
    // 一番下の立っている bit を削除
    i -= i & -i;
  }
  return ret;
}

// 0-index
void BIT::modify(int i, int v) {
  i = i + 1;
  assert(1 <= i && i <= m_size);
  while (i <= m_size) {
    m_data[i] += v;
    i += i & -i;
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n;
  cin >> n;
  vector<Ball> ps;
  vector<int> whitePos(n);
  vector<int> blackPos(n);

  for (int i = 0; i < 2 * n; i++) {
    char c;
    int a;
    cin >> c >> a;
    a--; // 0-origin
    ps.push_back(Ball{c, a});

    if (c == 'W')
      whitePos[a] = i;
    else
      blackPos[a] = i;
  }

  const auto where = [&](const Ball &b) {
    if (b.color == 'W')
      return whitePos[b.number];
    else
      return blackPos[b.number];
  };

  // -----------------------------------------------------------
  vector<vector<int>> costw(n + 1, vector<int>(n + 1));
  for (int i = 0; i <= n; i++) {
    // i 個白
    BIT tree(2 * n);
    for (int j = 0; j < i; j++)
      tree.modify(where(Ball{'B', j}), 1);

    for (int j = 0; j < n; j++) {
      int k = where(Ball({'W', j}));

      costw[j][i] = k - tree.query(k);
      tree.modify(k, 1);
    }
  }
  // -----------------------------------------------------------
  vector<vector<int>> costb(n + 1, vector<int>(n + 1));
  for (int i = 0; i <= n; i++) {
    // i 個黒
    BIT tree(2 * n);
    for (int j = 0; j < i; j++)
      tree.modify(where(Ball{'W', j}), 1);

    for (int j = 0; j < n; j++) {
      int k = where(Ball({'B', j}));

      costb[i][j] = k - tree.query(k);
      tree.modify(k, 1);
    }
  }

  vector<vector<int>> dp(n + 1, vector<int>(n + 1));
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      if (i == 0 && j == 0)
        continue;

      int useWhite = (i == 0) ? 1000000000 : (dp[i - 1][j] + costw[i - 1][j]);
      int useBlack = (j == 0) ? 1000000000 : (dp[i][j - 1] + costb[i][j - 1]);

      dp[i][j] = min(useWhite, useBlack);
    }
  }
  cout << dp[n][n] << endl;

  // cerr << "costw" << endl;
  // for (int i = 0; i <= n; i++) {
  //     for (int j = 0; j <= n; j++){
  //         cerr << costw[i][j] << ",";
  //     }
  //     cerr << endl;
  // }
  // cerr << "costb" << endl;
  // for (int i = 0; i <= n; i++) {
  //     for (int j = 0; j <= n; j++){
  //         cerr << costb[i][j] << ",";
  //     }
  //     cerr << endl;
  // }

  // cerr << "DP" << endl;
  // for (int i = 0; i <= n; i++){
  //     for (int j = 0; j <= n; j++){
  //         cerr << dp[i][j] << ",";
  //     }
  //     cerr << endl;
  // }

  // int white = 0;
  // int black = 0;

  // int ret = 0;

  // vector<Ball> shouldbe(2*n);
  // {
  //     int white = n - 1;
  //     int black = n - 1;
  //     for (int i = 2*n-1; i >= 0; i--) {
  //         int wp = -1;
  //         int bp = -1;
  //         for (int j = 0; j < 2 * n; j++) {
  //             if (ps[j].number == black && ps[j].color == 'B')
  //                 bp = j;
  //             if (ps[j].number == white && ps[j].color == 'W')
  //                 wp = j;
  //         }
  //         int s = max(bp, wp);
  //         shouldbe[i].color = (s == bp) ? 'B' : 'W';
  //         shouldbe[i].number = (s == bp) ? black : white;
  //         if (s == bp)
  //             black--;
  //         else
  //             white--;
  //     }
  // }
  // for (int i = 0; i < 2 * n; i++){
  //      cerr << "(" << shouldbe[i].color << "," << shouldbe[i].number << ")"
  //      << " ";
  // }
  // cerr << endl;

  // for (int i = 0; i < 2 * n; i++){
  //     int s = 0;
  //     for (int j = 0; j < 2 * n; j++) {
  //         if(ps[j].color == shouldbe[i].color && ps[j].number ==
  //         shouldbe[i].number)
  //             s = j;
  //     }
  //     for (int j = s; j >= i + 1; j--) {
  //        swap(ps[j - 1], ps[j]);
  //        ret++;
  //     }
  // }

  // for (int i = 0; i < 2 * n; i++) {
  //     int wp = 4 * n;
  //     int bp = 4 * n;
  //     for (int j = 0; j < 2 * n; j++) {
  //         if (ps[j].number == black && ps[j].color == 'B')
  //             bp = j;
  //             if (ps[j].number == white && ps[j].color == 'W')
  //                 wp = j;
  //         }
  //         int s = (bp < wp) ? bp : wp;
  //         for (int j = s; j >= i + 1; j--) {
  //             swap(ps[j - 1], ps[j]);
  //             ret++;
  //         }
  //         if (bp < wp)
  //             black++;
  //         else
  //             white++;
  //     }
  // for (int i = 0; i < 2 * n; i++){
  //     cerr << "(" << ps[i].color << "," << ps[i].number << ")" << " ";
  // }
  // cerr << endl;
  // cout << ret << endl;
  return 0;
}