#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |