結果
問題 |
No.952 危険な火薬庫
|
ユーザー |
![]() |
提出日時 | 2025-05-15 23:54:35 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 280 ms / 2,000 ms |
コード長 | 3,175 bytes |
コンパイル時間 | 3,796 ms |
コンパイル使用メモリ | 291,488 KB |
実行使用メモリ | 147,112 KB |
最終ジャッジ日時 | 2025-05-15 23:54:43 |
合計ジャッジ時間 | 6,905 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
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_monotone(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(); }