Submission #921765

#TimeUsernameProblemLanguageResultExecution timeMemory
921765ArpSplit the sequence (APIO14_sequence)C++17
100 / 100
1434 ms93756 KiB
#include<bits/stdc++.h>
using namespace std;
 
using i64 = long long;
 
const i64 inf = 1e18;
struct Line{
  i64 m,c;
  int i;
  Line() {
    cin >> m >> c;
  }
  Line(i64 _m,i64 _c,int _i) : m(_m),c(_c),i(_i) {}
  i64 getval(i64 x){
    i64 y =  m*1LL*x + c;
    return y;
  }
  i64 inc(Line L){
    if(this->m == L.m){
      return (this->c > L.c ? -inf : inf);
    }
    double x = 1.0 * (L.c - this->c) / (this->m - L.m);  
    // if(x < 0) return inf; 
    return floor(x);
  }    
};
struct Hull{
  vector<Line> lines;
  vector<i64> rng;
  void init(){
    lines.clear();
    rng.clear();
    lines.push_back(Line(0,-1,-1));
    rng.push_back(inf);
    // cout << "Line size is " << lines.size() << '\n';
  }
  void insert_line(Line L){
    // removing 100% faltu lines
    while(lines.size() >= 2){
      i64 x = L.inc(lines.back());
      i64 l = rng[rng.size() - 2] + 1;
      // assert(l > -inf);
      if(x < l){
        lines.pop_back();
        rng.pop_back();
      }else{
        break;
      }
    }
    if(lines.empty()){
      lines.push_back(L);
      rng.push_back(inf);
    }else{
      i64 x = L.inc(lines.back());
      if(x == inf) return;
      rng[rng.size() - 1] = x;
      rng.push_back(inf);
      lines.push_back(L);
    }
  }
  Line query(i64 x){
    int low = lower_bound(rng.begin(),rng.end(),x) - rng.begin();
    return lines[low];
  }
};
 
int main(){
 
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int n,k;
  cin >> n >> k;
  vector<int> a(n + 1);
  for(int i = 1;i <= n;i++){
    cin >> a[i];
  }
  vector<i64> pref(n + 1);
  for(int i = 1;i <= n;i++){
    pref[i] = pref[i - 1] + a[i];
  }
  auto S = [&](int i,int j){
    return pref[j] - pref[i]; 
  };
  vector<vector<int>> best(n + 1,vector<int>(k + 1,-1));
  // vector<vector<i64>> dp(n + 1,vector<i64>(k + 1,-inf));
  vector<i64> cur_dp(n + 1,-inf),prev_dp(n + 1,0);
  Hull hull;
  hull.insert_line(Line(0,0,0));
  for(int i = 1;i <= k;i++){
    vector<Line> lines(n);
    for(int j = 1;j < n;j++){
      if(best[j][i - 1] == -1) continue;
      // assert(dp[j][i - 1] >= 0);
      i64 m = S(0,j);
      i64 c = -m * 1LL * S(0,n) + prev_dp[j];
      lines[j] = (Line(m,c,j));
    }  
    for(int j = 1;j < n;j++){
      i64 x = S(0,j);
      Line ans = hull.query(x);
      i64 val = ans.getval(x);
      if(best[j][i - 1] != -1){
        hull.insert_line(lines[j]);
      }
      if(val < 0) continue;
      i64 C = x * 1LL * (S(0,n) - x);
      cur_dp[j] = val + C;
      best[j][i] = ans.i;
    }
    prev_dp = cur_dp;
    cur_dp = vector<i64>(n + 1,-inf);
    hull.init();
  }
  int x = 0;
  i64 maxi = 0;
  for(int i = n - 1;i >= 1;i--){
    if(prev_dp[i] >= maxi){
      x = i;
      maxi = prev_dp[i];
    }
  }
  vector<int> ans;
  while((int) ans.size() < k){
    ans.push_back(x);
    x = best[x][k - ans.size() + 1];
  }
  // assert(ans.size() == k);
  cout << maxi << '\n';
  for(int i = ans.size() - 1;i >= 0;i--){
    cout << ans[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...