Submission #1176736

#TimeUsernameProblemLanguageResultExecution timeMemory
1176736ivazivaSplit the sequence (APIO14_sequence)C++20
71 / 100
2097 ms43540 KiB
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>

using namespace std;

#define MAXN 100001
#define MAXM 201
#define int long long
#define ll long long

bool Q=true;

struct Line {
    mutable ll k, m, p;
    bool operator<(const Line& o) const {
        return Q ? p < o.p : k < o.k;
    }
};
 
struct LineContainer : multiset<Line> {
    // (for doubles, use inf = 1/.0, div(a,b) = a/b)
    const ll inf = LLONG_MAX;
    ll div(ll a, ll b) { // floored division
        return a / b - ((a ^ b) < 0 && a % b); }
    bool isect(iterator x, iterator y) {
        if (y == end()) { x->p = inf; return false; }
        if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
        else x->p = div(y->m - x->m, x->k - y->k);
        return x->p >= y->p;
    }
    void addLine(ll k, ll m) {
        auto z = insert({k, m, 0}), y = z++, x = y;
        while (isect(y, z)) z = erase(z);
        if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
        while ((y = x) != begin() && (--x)->p >= y->p)
            isect(x, erase(y));
    }
    pair<long long,long long> getMax(ll x) {
        assert(!empty());
        Q = 1; auto l = *lower_bound({0,0,x}); Q = 0;
        return {l.k,l.m};
    }
};

int n,k;
int pref[MAXN],dp[2][MAXN],where[MAXM][MAXN];
map<pair<int,int>,int> mapa;
LineContainer tree;
vector<int> ans;

int eval(pair<int,int> linija,int x){return (long long)(linija.first*x)+linija.second;}

int32_t main()
{
    ios_base::sync_with_stdio(false);
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);cin>>n>>k;pref[0]=0;
    for (int i=1;i<=n;i++) {cin>>pref[i];pref[i]+=pref[i-1];}
    for (int i=1;i<n;i++) dp[0][i]=(long long)(pref[i]*(pref[n]-pref[i]));
    for (int br=2;br<=k;br++)
    {
        for (int pos=br;pos<n;pos++)
        {
            tree.addLine(pref[pos-1],dp[0][pos-1]-(long long)(pref[pos-1]*pref[n]));
            mapa[{pref[pos-1],dp[0][pos-1]-(long long)(pref[pos-1]*pref[n])}]=pos-1;
            pair<int,int> resenje=tree.getMax(pref[pos]);dp[1][pos]=(long long)(pref[pos]*(pref[n]-pref[pos]))+eval(resenje,pref[pos]);
            where[br][pos]=mapa[resenje];
        }
        for (int pos=br;pos<n;pos++) dp[0][pos]=dp[1][pos];
        tree.clear();mapa.clear();
    }
    int maks=dp[0][k],pos=k;
    for (int i=k+1;i<n;i++)
    {
        if (dp[0][i]>maks) {maks=dp[0][i];pos=i;}
    }
    cout<<maks<<endl;ans.push_back(pos);
    for (int i=k;i>=2;i--) {ans.push_back(where[i][pos]);pos=where[i][pos];}
    for (int pos=ans.size()-1;pos>=0;pos--) cout<<ans[pos]<<" ";
    cout<<endl;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...