結果

問題 No.952 危険な火薬庫
ユーザー drken1215
提出日時 2025-05-15 12:51:51
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
MLE  
実行時間 -
コード長 5,532 bytes
コンパイル時間 6,654 ms
コンパイル使用メモリ 320,632 KB
実行使用メモリ 543,264 KB
最終ジャッジ日時 2025-05-15 12:52:03
合計ジャッジ時間 8,544 ms
ジャッジサーバーID
(参考情報)
judge2 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other MLE * 1 -- * 22
権限があれば一括ダウンロードができます

ソースコード

diff #

#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
/*
    Func:Monge 性を仮定
    - MIN: クエリ x の取りうる最小値
    - MAX: クエリ x の取りうる最大値 (f_i(MAX) がオーバーフローしないように注意)
    - INF: 最大値
 
    - insert (Func f_i): add f_i, O(log N)
    - query (x): min_i{ f_i(x) }, O(log N)
*/
template<class T> struct CHT {
    using Func = function<T(T)>;
    struct Node {
        Func func;
        Node *left, *right;
        Node(const Func& f) : left(nullptr), right(nullptr) {
            func = f;
        }
    };
    
    const T MIN, MAX, INF;
    Node* root;
    
    CHT(T MIN, T MAX, T INF) : MIN(MIN), MAX(MAX), INF(INF), root(nullptr) { }
    Node* insert(Node* p, T low, T high, Func& f) {
        if (!p) return new Node(f);
        if (p->func(low) <= f(low) && p->func(high) <= f(high)) return p;
        if (p->func(low) >= f(low) && p->func(high) >= f(high)) {
            p->func = f;
            return p;
        }
        T mid = (low + high) / 2;
        if (p->func(mid) > f(mid)) swap(p->func, f);
        if (p->func(low) >= f(low)) p->left = insert(p->left, low, mid, f);
        else p->right = insert(p->right, mid, high, f);
        return p;      
    }
    void insert(Func f) {
        root = insert(root, MIN, MAX, f);
    }
    T query(Node* p, T low, T high, T x) {
        if (!p) return INF;
        if (low == high) return p->func(x);
        T mid = (low + high) / 2;
        if (x <= mid) return min(p->func(x), query(p->left, low, mid, x));
        else return min(p->func(x), query(p->right, mid, high, x));
    }
    T query(T x) {
        return query(root, MIN, MAX, x);
    }
};



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>(0, MAX, INF));
    
    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] + (x - S[i]) * (x - S[i]);
        };
        if (dp[i][j][0] < INF / 2) chts[i-j].insert(func);

        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]-S[i-j])^2
            // dp[i-j+1][1][0] + (S[i]-S[i-j+1])^2
            // ...
            // dp[i-1][j-1][0] + (S[i]-S[i-1])^2
            chmin(dp[i][j][1], chts[i-j].query(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;
    }
}
0