This article is copyright ljh2000 and Blog Park is shared, welcome reprint, but must retain this statement, and give the original link, thank you for your cooperation.
This article ljh2000
Author Blog: http://www.cnblogs.com/ljh2000-jump/
Reprint Please specify the source, infringement must investigate, retain the final interpretation right!
Title Link: http://uoj.ac/problem/104
Positive solution: dp+ slope optimization
Problem Solving Report:
easy to find, the answer is only related to the division, and the order is irrelevant.
So the naïve equation is easy to get:
Make ${s[n]=\sum_{i=1}^{n}a[i]}$
${f[i][k]=max (f[j][k-1]+s[j]* (s[i]-s[j)), j<i}$
For ${j1,j2}$ and satisfies ${j1<j2}$,${f[j1][k-1]<f[j2][k-1]}$, obviously $j1$ can be deleted, then
${f[j1][k-1]+s[j1]* (S[i]-s[j1]) < f[j2][k-1]+s[j2]* (S[i]-s[j2])}$
After simplification:
${f[j1][k-1]-f[j2][k-1]+s[j2]^2-s[j1]^2 > s[i]* (s[j2]-s[j1])}$
Make ${g[i][k]=f[i][k]-s[i]^2}$
Then ${g[j1][k-1]-g[j2][k-1]>s[i]* (s[j2]-s[j1])}$
By this step, the positive solution is ready. Obviously we can use the slope optimization + monotone queue, the DP optimization to $o (NK) $, do k times, each time just sweep once.
If the first team satisfies the above formula, it is deleted directly. At the end of the team, look at the trend of slope change, if not satisfied then pop off.
It is made by Ljh2000#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio > #include <cmath> #include <algorithm> #include <vector> #include <queue> #include < Complex>using namespace Std;typedef long long ll;const int maxn = 100011;int n,k,dui[maxn],head,tail; LL g[maxn],s[maxn],f[maxn],f[maxn];int ans[maxn],pre[maxn][211];inline int getint () {int w=0,q=0; char C=getchar (); whi Le ((c< ' 0 ' | | C> ' 9 ') && c!= '-') C=getchar (); if (c== '-') Q=1,c=getchar (); while (c>= ' 0 ' &&c<= ' 9 ') w=w*10+c-' 0 ', C=getchar (); return q?-w:w;} Inline LL calc (int i,int j1,int J2) {return s[i]* (s[j2]-s[j1]);} inline void work () {n=getint (); K=getint (), for (int i=1;i<=n;i++) S[i]=getint (), for (int i=2;i<=n;i++) s[i]+=s[i-1 ]; for (int i=1;i<=n;i++) g[i]=-s[i]*s[i];for (int nowk=2;nowk<=k+1;nowk++) {head=tail=0;dui[++tail]=nowk-1; int i=nowk;i<=n;i++) {while (Head<tail && calc (i,dui[head],dui[head+1])>= (g[dui[head]]-g[dui[head+1])) head++; f[i]=f[dui[head]]+s[dui[head]]* (S[i]-s[dui[head]); Pre[i][nowk-1]=dui[head];while (Head<tail && (G[dui[tail-1]]-g[dui[tail]) * (S[i]-s[dui[tail]]) >= (g[ Dui[tail]]-g[i]) * (S[DUI[TAIL]]-S[DUI[TAIL-1])) tail--;d ui[++tail]=i;} for (int i=nowk;i<=n;i++) f[i]=f[i],g[i]=f[i]-s[i]*s[i];} printf ("%lld\n", F[n]); for (int i=n,j=k;i>0;j--) i=pre[i][j],ans[j]=i;for (int i=1;i<=k;i++) printf ("%d", Ans[i] );} int main () {work (); return 0;}
UOJ104 "APIO2014" Split the sequence