http://codeforces.com/problemset/problem/940/E

思路:可以想到划分成k个长度为c的区间得到的答案一定比长度为k*c的区间要好
长度c+a的区间和c,a的区间得到的答案是一样的,这就很明显就是个dp了
dp【i】=min(dp【i-1】+a【i】,dp【i-c】+s【i】-s【i-c】-min(i-c+1~c));

代码:

#include<bits/stdc++.h>
using namespace std;;
typedef long long ll;
ll a[100010];
ll s[100010];
ll dp[100100];
int m[100100];
set<ll>st;
map<ll,int>mp;
int main()
{

     int n,c;
     scanf("%d %d",&n,&c);
     for(int i=1;i<=n;i++) scanf("%lld",&a[i]),dp[i]=s[i]=s[i-1]+a[i];

     if(c==1) {
        printf("0\n");
        return 0;
     }
     for(int i=1;i<=c;i++){
        st.insert(a[i]);
        mp[a[i]]++;
        m[i]=*st.begin();
     }
     for(int i=c+1;i<=n;i++){
        st.insert(a[i]);
        mp[a[i]]++;
        mp[a[i-c]]--;
        if(mp[a[i-c]]==0) st.erase(a[i-c]);
        m[i]=*st.begin();
     }
     for(int i=c;i<=n;i++){//
        dp[i]=min((dp[i-1]+a[i]),(dp[i-c]+s[i]-s[i-c]-m[i]));
     }

     printf("%lld\n",dp[n]);
}