제출 #898931

#제출 시각아이디문제언어결과실행 시간메모리
898931NeroZeinSplit the sequence (APIO14_sequence)C++17
100 / 100
584 ms81932 KiB
#include "bits/stdc++.h"
using namespace std;

#ifdef Nero
#include "Deb.h"
#else
#define deb(...)
#endif

const int K = 202;
const int N = 1e5 + 5;

int a[N];
int last[K][N];
int pref[N], suf[N];
long long dp[N], dp2[N];

struct Line {
  int m;
  long long b;
  Line(int m_, long long b_) : m(m_), b(b_) {}
  long long val(int x) {
    return (long long) m * x + b; 
  }
  long double intersection(Line l) {
    assert(l.m != m); 
    return (b - l.b) / (l.m - m);
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, k;
  cin >> n >> k;
  for (int i = 1; i <= n; ++i) {
    cin >> a[i];
  }
  for (int i = 1; i <= n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }
  for (int i = n; i >= 1; --i) {
    suf[i] = suf[i + 1] + a[i]; 
  }
  int ind = 0;
  long long ans = -LLONG_MAX; 
  for (int j = 1; j <= k; ++j) {
    deque<pair<Line, int>> vec;
    vec.emplace_back(Line(-pref[j - 1], dp[j - 1]), j - 1);
    for (int i = j; i < n; ++i) {
      if (a[i] == 0) {
        dp2[i] = dp2[i - 1];
        last[j][i] = (last[j][i - 1] ? last[j][i - 1] : i - 1);
        continue; 
      }
      while (vec.size() >= 2) {
        if (vec[0].first.val(suf[i + 1]) <= vec[1].first.val(suf[i + 1])) {
          vec.pop_front();
        } else {
          break;
        }
      }
      dp2[i] = (long long) pref[i] * suf[i + 1] + vec.front().first.val(suf[i + 1]); 
      last[j][i] = vec.front().second; 
      Line cur = Line(-pref[i], dp[i]);
      while (vec.size() >= 2) {
        int m = (int) vec.size();
        if (cur.intersection(vec[m - 1].first) >= vec[m - 2].first.intersection(vec[m - 1].first)) {
          vec.pop_back();
        } else {
          break;
        }
      }
      vec.emplace_back(cur, i); 
    }
    for (int i = 1; i <= n; ++i) {
      dp[i] = dp2[i];
      if (j == k && dp[i] > ans) {
        ind = i;
        ans = dp[i]; 
      }
    }
  }
  cout << ans << '\n';
  vector<int> path;
  int cnt = k;
  while (cnt) {
    assert(ind); 
    path.push_back(ind);
    ind = last[cnt--][ind];
  }
  reverse(path.begin(), path.end());
  for (int i : path) {
    cout << i << ' ';
  }
  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...