結果
| 問題 |
No.952 危険な火薬庫
|
| ユーザー |
drken1215
|
| 提出日時 | 2025-05-15 23:53:40 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,543 ms / 2,000 ms |
| コード長 | 3,166 bytes |
| コンパイル時間 | 4,190 ms |
| コンパイル使用メモリ | 291,080 KB |
| 実行使用メモリ | 295,648 KB |
| 最終ジャッジ日時 | 2025-05-15 23:53:57 |
| 合計ジャッジ時間 | 14,883 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 23 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
// Convex Hull Trick
/*
追加クエリの直線の傾きが単調減少の場合
- insert (a, b): add y = ax + b
- query (x): min_i{a[i]*x + b}
*/
template<class T> struct CHT {
using Line = pair<T, T>;
deque<Line> lines;
T INF;
CHT(T inf = numeric_limits<T>::max() / 2) : INF(inf) {}
bool check(const Line &a, const Line &b, const Line &c) {
return (b.first - a.first) * (c.second - b.second)
>= (b.second - a.second) * (c.first - b.first);
}
T get(int k, T x) {
if (lines.empty() || k >= lines.size()) return INF;
assert(k >= 0 && k < lines.size());
return lines[k].first * x + lines[k].second;
}
void insert(T a, T b) {
Line l(a, b);
while (lines.size() >= 2
&& check(lines[(int)lines.size()-2], lines[(int)lines.size()-1], l)) {
lines.pop_back();
}
lines.push_back(l);
}
T query(T x) {
int low = -1, high = (int)lines.size();
while (high - low > 1) {
int mid = (low + high) / 2;
if (get(mid, x) >= get(mid + 1, x)) low = mid;
else high = mid;
}
return get(high, x);
}
// クエリの単調性も成り立つ場合 (x が単調増加)
T query_monotone(T x) {
while (lines.size() >= 2 && get(0, x) >= get(1, x)) lines.pop_front();
if (lines.empty()) return INF;
return lines[0].first * x + lines[0].second;
}
};
// yukicoder No.952 危険な火薬庫
using i128 = __int128;
constexpr i128 to_integer(const string &s) {
i128 res = 0;
for (auto c : s) {
if (isdigit(c)) res = res * 10 + (c - '0');
}
if (s[0] == '-') res *= -1;
return res;
}
istream& operator >> (istream &is, i128 &x) {
string s;
is >> s;
x = to_integer(s);
return is;
}
ostream& operator << (ostream &os, const i128 &x) {
i128 ax = (x >= 0 ? x : -x);
char buffer[128];
char *d = end(buffer);
do {
--d;
*d = "0123456789"[ax % 10];
ax /= 10;
} while (ax != 0);
if (x < 0) {
--d;
*d = '-';
}
int len = end(buffer) - d;
if (os.rdbuf()->sputn(d, len) != len) {
os.setstate(ios_base::badbit);
}
return os;
}
void yukicoder_952() {
int N;
cin >> N;
N++;
vector<i128> A(N, 0), S(N+1, 0);
for (int i = 0; i < N; i++) {
if (i) cin >> A[i];
S[i+1] = S[i] + A[i];
}
vector chts(N+1, CHT<i128>());
i128 INF = i128(1)<<100;
vector dp(N+1, vector(N+1, INF));
auto push = [&](int i, int j) -> void {
if (i-1 >= 0) chts[i-j].insert(-S[i]*2, S[i]*S[i] + dp[i-1][j]);
};
dp[0][0] = 0;
push(0, 0);
for (int i = 1; i <= N; i++) {
for (int j = 0; j < i; j++) {
dp[i][j] = min(dp[i][j], dp[i-1][j]);
dp[i][j] = min(dp[i][j], chts[i-j].query(S[i]) + S[i] * S[i]);
push(i, j);
}
}
for (int k = 1; k < N; k++) {
cout << dp[N][k] << endl;
}
}
int main() {
yukicoder_952();
}
drken1215