제출 #1288539

#제출 시각아이디문제언어결과실행 시간메모리
1288539harryleee수열 (APIO14_sequence)C++20
11 / 100
1 ms584 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 1e5;
int n, k;
ll a[MAXN + 1], pre[MAXN + 1];
int trace[MAXN + 1][201];
ll dp[MAXN + 1][201];
int bestPos = 0;

struct Line {
    ll a, b;
    mutable long double p;
    int id;
    bool operator<(const Line& other) const { return a < other.a || (a == other.a && b < other.b); }
    bool operator<(long double x) const { return p < x; } // heterogeneous lookup
};

struct LINE_CONTAINER {
    multiset<Line, less<>> ms;
    static constexpr long double INF = 1e30L;

    bool isect(multiset<Line, less<>>::iterator x, multiset<Line, less<>>::iterator y) {
        if (y == ms.end()) {
            x->p = INF;
            return false;
        }
        if (x->a == y->a) {
            x->p = (x->b >= y->b ? INF : -INF);
        } else {
            x->p = (long double)(y->b - x->b) / (long double)(x->a - y->a);
        }
        return x->p >= y->p;
    }

    void add(ll slope, ll intercept, int id) {
        auto it = ms.insert({slope, intercept, 0.0L, id});
        auto z = next(it);
        while (isect(it, z)) z = ms.erase(z);
        if (it != ms.begin()) {
            auto y = prev(it);
            if (isect(y, it)) { ms.erase(it); return; }
        }
        auto y = it;
        while (y != ms.begin()) {
            auto x = prev(y);
            if (isect(x, y)) {
                isect(x, ms.erase(y));
                y = x;
            } else break;
        }
    }

    // trả về {value, id} hoặc {NEG,0} nếu rỗng
    pair<ll,int> query(ll X) {
        if (ms.empty()) return {LLONG_MIN/4, 0};
        auto it = ms.lower_bound((long double)X); // dùng operator<(long double)
        if (it == ms.end()) --it;
        // tính bằng __int128 để tránh overflow
        __int128 val = (__int128)it->a * (__int128)X + (__int128)it->b;
        ll out;
        if (val > ( (__int128)LLONG_MAX )) out = LLONG_MAX;
        else if (val < ( (__int128)LLONG_MIN )) out = LLONG_MIN;
        else out = (ll)val;
        return {out, it->id};
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    if (!(cin >> n >> k)) return 0;
    for (int i = 1; i <= n; ++i) { cin >> a[i]; pre[i] = pre[i-1] + a[i]; }

    const ll NEG = LLONG_MIN / 4;
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= k; ++j) {
            dp[i][j] = NEG;
            trace[i][j] = 0;
        }
    dp[0][0] = 0;

    vector<LINE_CONTAINER> lc(max(1, k)); // containers for j = 0..k-1
    lc[0].add(0LL, 0LL, 0);

    for (int i = 1; i <= n; ++i) {
        // duyệt j giảm để tránh dùng chính dòng vừa thêm trong cùng i
        for (int j = min(i, k); j >= 1; --j) {
            auto g = lc[j-1].query(pre[n] - pre[i]);
            if (g.first > NEG/2) {
                // tính an toàn với __int128
                __int128 tmp = (__int128)g.first + (__int128)pre[i] * (__int128)(pre[n] - pre[i]);
                ll val;
                if (tmp > (__int128)LLONG_MAX) val = LLONG_MAX;
                else if (tmp < (__int128)LLONG_MIN) val = LLONG_MIN;
                else val = (ll)tmp;
                dp[i][j] = val;
                trace[i][j] = g.second; // lưu id chỉ khi dp hợp lệ
                if (j < k && dp[i][j] > NEG/2) lc[j].add(-pre[i], dp[i][j], i);
                if (j == k && i < n && dp[i][k] > dp[bestPos][k]) bestPos = i;
            }         }
    }

    cout << dp[bestPos][k] << '\n';
    int curPos = bestPos, curK = k;
    vector<int> cuts;
    while (curPos != 0 && curK > 0) {
        cuts.push_back(curPos);
        int prev = trace[curPos][curK];
        curPos = prev;
        --curK;
    }
    reverse(cuts.begin(), cuts.end());
    for (int x : cuts) cout << x << ' ';
    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...