BZOJ 1150: [CTSC2007]数据备份Backup
F[0/1][i][j]表示i不取/取,i和i之前共取了j个的最小距离,wqs二分,最后那个特判0略显有毒
#include<cstdio> #include<cstring> using namespace std; int n,k,s[1000005]; struct node{ long long val; int num; }F[2][100005]; node check(long long key){ for (int i=1; i<=n+1; i++) F[0][i]=F[1][i]=(node){1e9,1e9}; F[0][1]=(node){0,0}; for (int i=2; i<=n+1; i++){ if (F[0][i-1].val<F[1][i-1].val || F[0][i-1].val==F[1][i-1].val && F[0][i-1].num<=F[1][i-1].num) F[0][i]=F[0][i-1]; else F[0][i]=F[1][i-1]; F[1][i]=(node){F[0][i-1].val+s[i]-s[i-1]-key,F[0][i-1].num+1}; } return F[0][n+1]; } int main(){ scanf("%d%d",&n,&k); long long L=0,R=0; for (int i=1; i<=n; i++){ scanf("%d",&s[i]); R+=s[i]; } while (L<R){ long long mid=(L+R+1)>>1; if (check(mid).num<=k) L=mid; else R=mid-1; } if (check(L).num<=k) printf("%lld\n",F[0][n+1].val+L*k); else printf("0\n"); return 0; }