結果
| 問題 |
No.952 危険な火薬庫
|
| ユーザー |
drken1215
|
| 提出日時 | 2025-05-15 16:17:58 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,328 bytes |
| コンパイル時間 | 3,879 ms |
| コンパイル使用メモリ | 317,616 KB |
| 実行使用メモリ | 568,888 KB |
| 最終ジャッジ日時 | 2025-05-15 16:18:13 |
| 合計ジャッジ時間 | 12,993 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 3 WA * 17 MLE * 3 |
ソースコード
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
template<class S, class T> inline bool chmax(S &a, T b) { return (a < b ? a = b, 1 : 0); }
template<class S, class T> inline bool chmin(S &a, T b) { return (a > b ? a = b, 1 : 0); }
using pint = pair<int, int>;
using pll = pair<long long, long long>;
using tint = array<int, 3>;
using tll = array<long long, 3>;
using fint = array<int, 4>;
using fll = array<long long, 4>;
using vint = vector<int>;
using vll = vector<long long>;
using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using int128 = __int128;
using u128 = unsigned __int128;
template <class T>
using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;
#define REP(i, a) for (long long i = 0; i < (long long)(a); i++)
#define REP2(i, a, b) for (long long i = a; i < (long long)(b); i++)
#define RREP(i, a) for (long long i = (a)-1; i >= (long long)(0); --i)
#define RREP2(i, a, b) for (long long i = (b)-1; i >= (long long)(a); --i)
#define EB emplace_back
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define FI first
#define SE second
#define ALL(x) x.begin(), x.end()
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
// debug stream
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, deque<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T> ostream& operator << (ostream &s, multiset<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }
// 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;
inline 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);
}
inline T get(int k, T x) {
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 1LL<<60;
return lines[0].first * x + lines[0].second;
}
};
int main() {
int N;
cin >> N;
vector<ll> A(N), S(N+1, 0);
REP(i, N) {
cin >> A[i];
S[i+1] = S[i] + A[i];
}
ll MAX = 1LL<<29, INF = 1LL<<60;
vector<CHT<ll>> chts(N+1, CHT<ll>());
vector dp(N+1, vector(N+1, vector(2, INF))); // 0: 白で終わる, 1: 黒で終わる
vector mdp(N+2, vector(N+1, INF));
auto push = [&](int i, int j) -> void {
// auto func = [i, j, &S, &dp](ll x) -> ll {
// return dp[i][j][0] + S[i-j]*S[i-j]
// };
chts[i-j].insert(-S[i]*2, S[i]*S[i] + dp[i][j][0]);
chmin(mdp[i+1][j], min(mdp[i][j], dp[i][j][1]));
};
dp[0][0][0] = 0, dp[0][0][1] = 0;
push(0, 0);
REP2(i, 1, N+1) {
//COUT(i);
REP(j, i+1) {
// 0 -> 1
// REP2(k, 0, j) {
// chmin(dp[i][j][1], dp[i-j+k][k][0] + (S[i] - S[i-j+k]) * (S[i] - S[i-j+k]));
// }
// (dp[i-j][0][0] + S[i]² - 2S[i]S[i-j] + S[i-j]²
// dp[i-j+1][1][0] + S[i]² - 2S[i]S[i-j+1] + S[i-j+1]²
// ...
// dp[i-1][j-1][0] + S[i]² - 2S[i]S[i-1] + S[i-1]²
chmin(dp[i][j][1], chts[i-j].query_monotone(S[i]) + S[i] * S[i]);
// 1 -> 0
// REP(k, i) {
// chmin(dp[i][j][0], dp[k][j][1]);
// }
chmin(dp[i][j][0], mdp[i][j]);
//cout << i << ", " << j << ": " << make_pair(dp[i][j][0], dp[i][j][1]) << endl;
push(i, j);
}
}
REP2(k, 1, N+1) {
cout << min(dp[N][k][0], dp[N][k][1]) << endl;
}
}
drken1215