Submission #108393

#TimeUsernameProblemLanguageResultExecution timeMemory
108393DiuvenSplit the sequence (APIO14_sequence)C++14
100 / 100
996 ms83452 KiB
#include <bits/stdc++.h> using namespace std; typedef long long lint; typedef pair<int, int> pii; const int INF = 2e9; const int MOD = 1e9+7; const int MAX = 1e5+10; const lint LNF = 2e18; int n, p; lint S[MAX]; lint D[MAX], E[MAX]; int from[202][MAX]; struct frac{ lint a, b; // a/b , b>0 frac(lint x, lint y): a(x), b(y) { if(b==0){ cerr<<"ERROR!!\n", exit(42); } if(b<0) a*=-1, b*=-1; } frac(lint x): a(x), b(1) {} frac(): a(1), b(1) {} bool operator <= (const frac &f) { return a*f.b <= f.a*b; } bool operator <= (lint x) { return a <= x * b; } void show(){ cout<<a<<"/"<<b<<" ~= "<<(double)a/b<<endl; } }; struct line_t{ lint a, b; int idx; lint eval(lint x){ return a*x + b; } frac operator ^ (const line_t &l) const { return frac(l.b-b, a-l.a); } void show(){ cout<<a<<' '<<b<<endl; } }; deque<line_t> Q; /* D[i][j]: 1~i까지 j조각 최대 D[i][j] = max(D[k][j-1] + (S[i]S[k]-S[k]^2) = max(S[k] * S[i] + (D[k][j-1]-S[k]^2)) */ int main(){ ios::sync_with_stdio(0); cin.tie(0); cin>>n>>p; p++; for(int i=1, a; i<=n; i++) cin>>a, S[i]=S[i-1]+a; for(int i=1; i<=n; i++) D[i] = -LNF; D[0] = 0; for(int j=1; j<=p; j++){ Q.clear(); Q.push_back({0, D[0], 0}); E[0] = -INF; for(int i=1; i<=n; i++){ // cout<<"Solve: "<<i<<", "<<j<<endl; // for(line_t l:Q) l.show(); // cout<<endl; while(Q.size() > 1U){ // a,b가 S[i] 이하이면 pop_front line_t a = Q[0], b = Q[1]; if((a^b) <= S[i]) Q.pop_front(); else break; } E[i] = Q[0].eval(S[i]); from[j][i] = Q[0].idx; // cout<<"Midst\n"; line_t now = {S[i], D[i] - S[i]*S[i], i}; while(Q.size() > 1U){ // a,b가 now,b가 이하이면 pop_back line_t a = Q.back(), b = Q[Q.size()-2U]; if((now^b) <= (a^b)) Q.pop_back(); else break; } // 만약 평행하다면, 절편이 더 큰걸로 교체 if(!Q.empty() && Q.back().a == now.a){ if(Q.back().b <= now.b) Q.back().b = now.b, Q.back().idx = now.idx; } else Q.push_back(now); } for(int i=0; i<=n; i++) D[i] = E[i]; } int pos = -1; lint ans = -1; for(int i=1; i<=n; i++){ if(ans<D[i]) pos = i, ans = D[i]; } vector<int> track; for(int i=p; i>1; i--){ pos = from[i][pos]; track.push_back(pos); } cout<<ans<<'\n'; reverse(track.begin(), track.end()); for(int x:track) 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...