RT,最坏能被卡到 O(n2) 的代码过了。
实际上这份代码是正解用堆维护改成暴力求 min 的产物,代码如下:
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
cin.tie(nullptr) -> sync_with_stdio(false);
int n; i64 m;
cin >> n >> m;
vector <i64> a(n + 1), f(n + 1, 1e18);
for (int i = 1; i <= n; i ++) {
cin >> a[i];
if (a[i] > m) return cout << -1 << endl, 0;
}
deque <i64> q;
f[0] = 0;
i64 sum = 0;
for (int i = 1, j = 1; i <= n; i ++) {
sum += a[i];
while (!q.empty() && a[q.back()] < a[i]) q.pop_back();
q.push_back(i);
for (; sum > m; j ++) {
sum -= a[j];
if (q.front() == j) q.pop_front();
}
int r = j - 1;
for (auto &idx : q) {
f[i] = min(f[i], f[r] + a[idx]);
r = idx;
}
}
return cout << f[n] << endl, 0;
}
下面这份代码可以生成 hack:
#include <bits/stdc++.h>
using std::cin;
using std::cout;
static const unsigned RS =
std::chrono::steady_clock::now().time_since_epoch().count();
int main() {
std::mt19937_64 gen_64(RS);
int n; cin >> n;
int64_t m = 1e11, lim = m / n;
cout << n << ' ' << m << std::endl;
std::uniform_int_distribution <int64_t> dis(0, lim);
std::vector <int64_t> a(n);
for (int i = 0; i < n; i ++) a[i] = dis(gen_64);
std::sort (a.begin(), a.end(), std::greater <int64_t> ());
for (int i = 0; i + 1 < n; i ++) cout << a[i] << ' ';
cout << gen_64() % (int)m << std::endl;
return 0;
}