SOL: 我们注意到这道题等价于在i段中取 len/c (下取整)小的数,令其最大。
我们发现a>0,所以一个长度大于等于2c的段肯定劣于将其劈成两段大于c的区间。
我们又注意到,一个长度大于c而小于2c的区间,可以划分成一个长度为c的区间和一些长度为1的区间。
我们发现问题划归为划分成长度为1和c的区间。
#include<bits/stdc++.h> template <class T> #define gc getchar #define sight(c) ('0'<=c&&c<='9') inline void read(T &x){ static int b; static char c; for (b=1,c=gc();!sight(c);c=gc()) if (c=='-') b=-1; for (x=0;sight(c);c=gc()) x=x*10+c-48; x*=b; } using namespace std; #define N 100007 multiset<int> Ma; int n,a[N],c,pp; long long sum,f[N]; int main () { read(n); read(c); for (int i=1;i<=n;i++) read(a[i]),sum+=a[i]; for (int i=1;i<=n;i++) { f[i]=f[i-1]; Ma.insert(a[i]); if (i>=c) { pp=*Ma.begin(); f[i]=max(f[i],f[i-c]+pp); Ma.erase(Ma.find(a[i-c+1])); } } printf("%lld ",sum-f[n]); }