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

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

constexpr char newl = '\\n';
constexpr ll INF = 1e18;

// 1-indexであることに注意
template <typename T> struct BIT {
  int n;
  vector<T> data;
  int n_msb;

  BIT(int n) : n(n), data(n + 1, 0) {
    n_msb = 1;
    while (n_msb <= n)
      n_msb <<= 1;
    n_msb >>= 1;
  }

  T sum(int i) {
    T s = 0;
    while (i > 0) {
      s += data[i];
      i -= i & -i;
    }
    return s;
  }

  void add(int i, T x) {
    while (i <= n) {
      data[i] += x;
      i += i & -i;
    }
  }

  // sum(i) >= val となる最小のiを返す
  // ただし、sum(i)は広義単調増加すると仮定
  int lower_bound(T val) {
    if (val <= 0)
      return 0;

    int res = 0;
    for (int k = n_msb; k > 0; k >>= 1) {
      if (res + k <= n && data[res + k] < val) {
        val -= data[res + k];
        res += k;
      }
    }
    return res + 1;
  }
};

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

  int n;
  cin >> n;

  vector<ll> x(n), y(n), p(n);
  for (int i = 0; i < n; i++) {
    cin >> x[i] >> y[i] >> p[i];
  }

  const int geta = 10000;

  vector<ll> memo(1 << n, INF);
  memo[0] = 0;
  BIT<ll> bx(geta * 2 + 1), by(geta * 2 + 1);
  for (int i = 1; i < (1 << n); i++) {
    ll w = 0;
    for (int j = 0; j < n; j++) {
      if (i >> j & 1) {
        bx.add(x[j] + geta + 1, p[j]);
        by.add(y[j] + geta + 1, p[j]);
        w += p[j];
      }
    }

    ll midx = bx.lower_bound(w / 2) - geta - 1;
    ll midy = by.lower_bound(w / 2) - geta - 1;

    ll costx = 0, costy = 0;
    for (int j = 0; j < n; j++) {
      if (i >> j & 1) {
        costx += abs(x[j] - midx) * p[j];
        costy += abs(y[j] - midy) * p[j];
        bx.add(x[j] + geta + 1, -p[j]);
        by.add(y[j] + geta + 1, -p[j]);
      }
    }

    memo[i] = min(costx, costy);
    // cerr << i << ": " << memo[i] << newl;
  }

  vector<vector<ll>> dp(n + 1, vector<ll>(1 << n, INF));
  for (int i = 0; i < (1 << n); i++) {
    dp[0][i] = 0;
    for (int j = 0; j < n; j++) {
      if (i >> j & 1) {
        dp[0][i] += min(abs(x[j]), abs(y[j])) * p[j];
      }
    }
  }

  cout << dp[0][(1 << n) - 1] << newl;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (1 << n); j++) {
      for (int k = j;; k = (k - 1) & j) {
        dp[i + 1][j] = min(dp[i + 1][j], dp[i][k] + memo[j ^ k]);
        if (!k)
          break;
      }
    }

    cout << dp[i + 1][(1 << n) - 1] << newl;
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

constexpr char newl = '\\n';
constexpr ll INF = 1e18;

// 1-indexであることに注意
template <typename T> struct BIT {
  int n;
  vector<T> data;
  int n_msb;

  BIT(int n) : n(n), data(n + 1, 0) {
    n_msb = 1;
    while (n_msb <= n)
      n_msb <<= 1;
    n_msb >>= 1;
  }

  T sum(int i) {
    T s = 0;
    while (i > 0) {
      s += data[i];
      i -= i & -i;
    }
    return s;
  }

  void add(int i, T x) {
    while (i <= n) {
      data[i] += x;
      i += i & -i;
    }
  }

  // sum(i) >= val となる最小のiを返す
  // ただし、sum(i)は広義単調増加すると仮定
  int lower_bound(T val) {
    if (val <= 0)
      return 0;

    int res = 0;
    for (int k = n_msb; k > 0; k >>= 1) {
      if (res + k <= n && data[res + k] < val) {
        val -= data[res + k];
        res += k;
      }
    }
    return res + 1;
  }
};

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

  int n;
  cin >> n;

  vector<ll> x(n), y(n), p(n);
  for (int i = 0; i < n; i++) {
    cin >> x[i] >> y[i] >> p[i];
  }

  const int geta = 10000;

  vector<ll> memo(1 << n, INF);
  memo[0] = 0;
  for (int i = 1; i < (1 << n); i++) {
    ll w = 0;
    BIT<ll> bx(geta * 2 + 1), by(geta * 2 + 1);
    for (int j = 0; j < n; j++) {
      if (i >> j & 1) {
        bx.add(x[j] + geta + 1, p[j]);
        by.add(y[j] + geta + 1, p[j]);
        w += p[j];
      }
    }

    ll midx = bx.lower_bound(w / 2) - geta - 1;
    ll midy = by.lower_bound(w / 2) - geta - 1;

    ll costx = 0, costy = 0;
    for (int j = 0; j < n; j++) {
      if (i >> j & 1) {
        costx += abs(x[j] - midx) * p[j];
        costy += abs(y[j] - midy) * p[j];
      }
    }

    memo[i] = min(costx, costy);
    // cerr << i << ": " << memo[i] << newl;
  }

  vector<vector<ll>> dp(n + 1, vector<ll>(1 << n, INF));
  for (int i = 0; i < (1 << n); i++) {
    dp[0][i] = 0;
    for (int j = 0; j < n; j++) {
      if (i >> j & 1) {
        dp[0][i] += min(abs(x[j]), abs(y[j])) * p[j];
      }
    }
  }

  cout << dp[0][(1 << n) - 1] << newl;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (1 << n); j++) {
      for (int k = j;; k = (k - 1) & j) {
        dp[i + 1][j] = min(dp[i + 1][j], dp[i][k] + memo[j ^ k]);
        if (!k)
          break;
      }
    }

    cout << dp[i + 1][(1 << n) - 1] << newl;
  }

  return 0;
}