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

//  Copyright 2020 Nikita Golikov

#include <bits/stdc++.h>

using namespace std;

using i64 = int64_t;
using ui64 = uint64_t;

#ifdef GOLIKOV
mt19937_64 rng(566);
#else
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
#endif

template <typename T> T rnd_helper(T from, T to, true_type) {
  return uniform_int_distribution<T>(from, to)(rng);
}

template <typename T> T rnd_helper(T from, T to, false_type) {
  return uniform_real_distribution<T>(from, to)(rng);
}

template <typename T> T rnd(T from, T to) {
  return rnd_helper(from, to, is_integral<T>{});
}

template <typename A, typename B, typename Cmp>
bool set_min(A &x, B const &y, Cmp &&cmp) {
  if (cmp(y, x)) {
    x = y;
    return true;
  }
  return false;
}

template <typename A, typename B> bool set_min(A &x, B const &y) {
  return set_min(x, y, less<typename common_type<A, B>::type>{});
}

template <typename A, typename B> bool set_max(A &x, B const &y) {
  return set_min(x, y, greater<typename common_type<A, B>::type>{});
}

#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template <typename K, typename V>
using ordered_map =
    tree<K, V, less<K>, rb_tree_tag, tree_order_statistics_node_update>;

//  https://codeforces.com/blog/entry/62393
struct custom_hash {
  static uint64_t splitmix64(uint64_t x) {
    // http://xorshift.di.unimi.it/splitmix64.c
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }

  size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return static_cast<size_t>(splitmix64(x + FIXED_RANDOM));
  }
};

#ifdef __cpp_deduction_guides
template <typename F> struct rec_fun {
  F fun;

  rec_fun(F &&fun_) : fun(std::forward<F>(fun_)) {}

  template <typename... Args> decltype(auto) operator()(Args &&...args) const {
    return fun(*this, std::forward<Args>(args)...);
  }
};
#endif

#ifdef __cpp_inline_variables
template <typename T>
inline constexpr auto type_min = numeric_limits<T>::lowest();

template <typename T> inline constexpr auto type_max = numeric_limits<T>::max();
#endif

//  fast alloc
#if 0
int const MAX_MEM = 1e8;
int mpos = 0;
char mem[MAX_MEM];
void* operator new(size_t n) {
  mpos += n;
  return (void*)(mem + mpos - n);
}
void operator delete (void*) noexcept {}
#endif

//  pragmas
#if 0
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#pragma GCC optimize("unroll-loops")
#endif

vector<i64> solve(vector<pair<int, int>> a, int k) {
  int n = (int)a.size();
  sort(a.begin(), a.end());
  vector<i64> ans(k + 1, (i64)1e18);
  vector<int> cl_l(n, -1), cl_r(n, -1);
  for (int m = 0; m < (1 << n); ++m) {
    fill(cl_l.begin(), cl_l.end(), -1);
    fill(cl_r.begin(), cl_r.end(), -1);
    i64 score = 0;
    for (int i = 0; i < n; ++i) {
      if (i) {
        cl_l[i] = cl_l[i - 1];
        cl_r[n - i - 1] = cl_r[n - i];
      }
      if (m & (1 << i))
        cl_l[i] = i;
      if (m & (1 << (n - i - 1)))
        cl_r[n - i - 1] = n - i - 1;
    }
    for (int i = 0; i < n; ++i) {
      i64 cur = (i64)abs(a[i].first) * a[i].second;
      if (cl_l[i] >= 0)
        set_min(cur, (i64)a[i].second * (a[i].first - a[cl_l[i]].first));
      if (cl_r[i] >= 0)
        set_min(cur, (i64)a[i].second * (a[cl_r[i]].first - a[i].first));
      score += cur;
    }
    auto bits = __builtin_popcount(m);
    set_min(ans[bits], score);
  }
  for (int i = 1; i <= k; ++i)
    set_min(ans[i], ans[i - 1]);
  return ans;
}

int main() {
#ifdef GOLIKOV
  assert(freopen("in", "rt", stdin));
  auto _clock_start = chrono::high_resolution_clock::now();
#endif
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n;
  cin >> n;
  struct item {
    int x;
    int y;
    int p;
  };
  vector<item> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i].x >> a[i].y >> a[i].p;
  }
  vector<vector<i64>> ans_x(1 << n), ans_y(1 << n);
  for (int msk = 0; msk < (1 << n); ++msk) {
    vector<pair<int, int>> xs, ys;
    for (int i = 0; i < n; ++i) {
      if (msk & (1 << i)) {
        xs.emplace_back(a[i].x, a[i].p);
        ys.emplace_back(a[i].y, a[i].p);
      }
    }
    ans_y[msk] = solve(ys, n);
    ans_x[msk] = solve(xs, n);
  }
  vector<i64> ans(n + 1, (i64)1e18);
  for (int msk = 0; msk < (1 << n); ++msk) {
    for (int x = 0; x <= n; ++x) {
      for (int y = 0; x + y <= n; ++y) {
        set_min(ans[x + y], ans_x[msk][x] + ans_y[((1 << n) - 1) ^ msk][y]);
      }
    }
  }
  for (auto x : ans)
    cout << x << '\\n';

#ifdef GOLIKOV
  cerr << "Executed in "
       << chrono::duration_cast<chrono::milliseconds>(
              chrono::high_resolution_clock::now() - _clock_start)
              .count()
       << "ms." << endl;
#endif
  return 0;
}


Error: TLE

Fixed submission:

//  Copyright 2020 Nikita Golikov

#include <bits/stdc++.h>

using namespace std;

using i64 = int64_t;
using ui64 = uint64_t;

#ifdef GOLIKOV
mt19937_64 rng(566);
#else
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
#endif

template <typename T> T rnd_helper(T from, T to, true_type) {
  return uniform_int_distribution<T>(from, to)(rng);
}

template <typename T> T rnd_helper(T from, T to, false_type) {
  return uniform_real_distribution<T>(from, to)(rng);
}

template <typename T> T rnd(T from, T to) {
  return rnd_helper(from, to, is_integral<T>{});
}

template <typename A, typename B, typename Cmp>
bool set_min(A &x, B const &y, Cmp &&cmp) {
  if (cmp(y, x)) {
    x = y;
    return true;
  }
  return false;
}

template <typename A, typename B> bool set_min(A &x, B const &y) {
  return set_min(x, y, less<typename common_type<A, B>::type>{});
}

template <typename A, typename B> bool set_max(A &x, B const &y) {
  return set_min(x, y, greater<typename common_type<A, B>::type>{});
}

#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template <typename K, typename V>
using ordered_map =
    tree<K, V, less<K>, rb_tree_tag, tree_order_statistics_node_update>;

//  https://codeforces.com/blog/entry/62393
struct custom_hash {
  static uint64_t splitmix64(uint64_t x) {
    // http://xorshift.di.unimi.it/splitmix64.c
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }

  size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return static_cast<size_t>(splitmix64(x + FIXED_RANDOM));
  }
};

#ifdef __cpp_deduction_guides
template <typename F> struct rec_fun {
  F fun;

  rec_fun(F &&fun_) : fun(std::forward<F>(fun_)) {}

  template <typename... Args> decltype(auto) operator()(Args &&...args) const {
    return fun(*this, std::forward<Args>(args)...);
  }
};
#endif

#ifdef __cpp_inline_variables
template <typename T>
inline constexpr auto type_min = numeric_limits<T>::lowest();

template <typename T> inline constexpr auto type_max = numeric_limits<T>::max();
#endif

//  fast alloc
#if 0
int const MAX_MEM = 1e8;
int mpos = 0;
char mem[MAX_MEM];
void* operator new(size_t n) {
  mpos += n;
  return (void*)(mem + mpos - n);
}
void operator delete (void*) noexcept {}
#endif

//  pragmas
#if 0
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#pragma GCC optimize("unroll-loops")
#endif

vector<i64> solve(vector<pair<int, int>> a, int k) {
  int n = (int)a.size();
  sort(a.begin(), a.end());
  vector<i64> ans(k + 1, (i64)1e18);
  for (int m = 0; m < (1 << n); ++m) {
    i64 score = 0;
    vector<int> cl_l(n, -1), cl_r(n, -1);
    for (int i = 0; i < n; ++i) {
      if (i) {
        cl_l[i] = cl_l[i - 1];
        cl_r[n - i - 1] = cl_r[n - i];
      }
      if (m & (1 << i))
        cl_l[i] = i;
      if (m & (1 << (n - i - 1)))
        cl_r[n - i - 1] = n - i - 1;
    }
    for (int i = 0; i < n; ++i) {
      i64 cur = (i64)abs(a[i].first) * a[i].second;
      if (cl_l[i] >= 0)
        set_min(cur, (i64)a[i].second * (a[i].first - a[cl_l[i]].first));
      if (cl_r[i] >= 0)
        set_min(cur, (i64)a[i].second * (a[cl_r[i]].first - a[i].first));
      score += cur;
    }
    auto bits = __builtin_popcount(m);
    set_min(ans[bits], score);
  }
  for (int i = 1; i <= k; ++i)
    set_min(ans[i], ans[i - 1]);
  return ans;
}

int main() {
#ifdef GOLIKOV
  assert(freopen("in", "rt", stdin));
  auto _clock_start = chrono::high_resolution_clock::now();
#endif
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n;
  cin >> n;
  struct item {
    int x;
    int y;
    int p;
  };
  vector<item> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i].x >> a[i].y >> a[i].p;
  }
  vector<vector<i64>> ans_x(1 << n), ans_y(1 << n);
  for (int msk = 0; msk < (1 << n); ++msk) {
    vector<pair<int, int>> xs, ys;
    for (int i = 0; i < n; ++i) {
      if (msk & (1 << i)) {
        xs.emplace_back(a[i].x, a[i].p);
        ys.emplace_back(a[i].y, a[i].p);
      }
    }
    ans_y[msk] = solve(ys, n);
    ans_x[msk] = solve(xs, n);
  }
  vector<i64> ans(n + 1, (i64)1e18);
  for (int msk = 0; msk < (1 << n); ++msk) {
    for (int x = 0; x <= n; ++x) {
      for (int y = 0; x + y <= n; ++y) {
        set_min(ans[x + y], ans_x[msk][x] + ans_y[((1 << n) - 1) ^ msk][y]);
      }
    }
  }
  for (auto x : ans)
    cout << x << '\\n';

#ifdef GOLIKOV
  cerr << "Executed in "
       << chrono::duration_cast<chrono::milliseconds>(
              chrono::high_resolution_clock::now() - _clock_start)
              .count()
       << "ms." << endl;
#endif
  return 0;
}