Submission #1288545

#TimeUsernameProblemLanguageResultExecution timeMemory
1288545harryleee수열 (APIO14_sequence)C++20
71 / 100
2097 ms72152 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll NEG_INF = (ll)-9e18;
const ll INF = (ll)9e18;

int n, k;
vector<ll> a, pre;

// parentPacked: lưu (k+2) x (n+1) entries, mỗi entry 3 bytes (little-endian)
vector<unsigned char> parentPacked;

inline void set_parent(int layer, int idx, int val){
    size_t pos = ((size_t)layer * (n + 1) + idx) * 3;
    parentPacked[pos]     = (unsigned char)(val & 0xFF);
    parentPacked[pos + 1] = (unsigned char)((val >> 8) & 0xFF);
    parentPacked[pos + 2] = (unsigned char)((val >> 16) & 0xFF);
}
inline int get_parent(int layer, int idx){
    size_t pos = ((size_t)layer * (n + 1) + idx) * 3;
    int v = parentPacked[pos] | (parentPacked[pos + 1] << 8) | (parentPacked[pos + 2] << 16);
    return v;
}

struct line{
    long long a, b;
    mutable long double p;
    int id;
    bool operator < (const line& other) const {
        if (other.a == (long long)1e18 && other.b == (long long)1e18)
            return p < other.p;
        return a < other.a || (a == other.a && b < other.b);
    }
};

struct LINE_CONTAINER {
    multiset<line> ms;
    inline bool del(multiset<line>::iterator x, multiset<line>::iterator y){
        if (y == ms.end()){
            x->p = 1e18;
            return false;
        }
        if (x->a == y->a){
            x->p = (x->b >= y->b) ? 1e18 : -1e18;
        } else {
            x->p = (long double)(y->b - x->b) / (long double)(x->a - y->a);
        }
        return x->p >= y->p;
    }
    inline void update(long long a, long long b, int i){
        auto x = ms.insert({a,b,0.0L,i});
        auto y = next(x);
        while (del(x,y)) y = ms.erase(y);
        if (x != ms.begin()){
            y = prev(x);
            if (del(y,x)) ms.erase(x);
        } else y = x;
        while (y != ms.begin()){
            x = prev(y);
            if (del(x,y)){
                del(x, ms.erase(y));
                y = x;
            } else break;
        }
    }
    inline pair<long long,int> get(long long x){
        auto it = ms.lower_bound({(long long)1e18, (long long)1e18, (long double)x, 0});
        if (it == ms.end()) return {NEG_INF, 0};
        return { it->a * x + it->b, it->id };
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    if (!(cin >> n >> k)) return 0;
    a.assign(n+1,0);
    pre.assign(n+1,0);
    for (int i = 1; i <= n; ++i){ cin >> a[i]; pre[i] = pre[i-1] + a[i]; }

    // allocate packed parents: (k+2) layers * (n+1) entries * 3 bytes
    parentPacked.assign((size_t)(k + 2) * (n + 1) * 3, 0);

    // dp only 2 layers
    vector<ll> dp_prev(n+1, INF), dp_cur(n+1, INF);
    dp_prev[0] = 0;

    for (int c = 1; c <= k + 1; ++c){
        LINE_CONTAINER lc;
        // insert t=0 if valid
        if (dp_prev[0] < INF/4) lc.update(2LL * pre[0], -(dp_prev[0] + pre[0]*pre[0]), 0);

        // reset dp_cur
        fill(dp_cur.begin(), dp_cur.end(), INF);

        for (int i = 1; i <= n; ++i){
            auto g = lc.get(pre[i]);
            if (g.first != NEG_INF){
                ll val = pre[i]*pre[i] - g.first;
                if (val < dp_cur[i]){
                    dp_cur[i] = val;
                    // store parent t = g.second into packed array
                    set_parent(c, i, g.second);
                }
            }
            // add line for t = i to be used later
            if (dp_prev[i] < INF/4){
                ll slope = 2LL * pre[i];
                ll intercept = -(dp_prev[i] + pre[i]*pre[i]);
                lc.update(slope, intercept, i);
            }
        }
        dp_prev.swap(dp_cur);
    }

    ll total = pre[n] * pre[n];
    ll min_sumsq = dp_prev[n]; // dp[n][k+1]
    ll best_points = (total - min_sumsq) / 2;
    cout << best_points << '\n';

    // backtrack using packed parents
    vector<int> cuts;
    int cur = n;
    int layer = k + 1;
    while (layer > 0 && cur > 0){
        int prev = get_parent(layer, cur);
        if (prev == 0) break;
        cuts.push_back(prev);
        cur = prev;
        --layer;
    }
    reverse(cuts.begin(), cuts.end());
    // print first k cuts (between 1..n-1). (cuts size should be k)
    for (size_t i = 0; i < cuts.size() && (int)i < k; ++i){
        if (i) cout << ' ';
        cout << cuts[i];
    }
    cout << '\n';
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...