题解:
显然可以dp[i][j]表示到第i个,选了j个的最优解
单调队列优化
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define pii pair<ll,int> 4 #define mp(a,b) make_pair(a,b) 5 #define maxn 5005 6 using namespace std; 7 int n,k,x; 8 struct Que 9 { 10 int l,r; 11 pii a[maxn]; 12 void init(){l=r=0;} 13 bool empty(){return l==r;} 14 void push(pii x) 15 { 16 while(!empty()&&a[r]<x)r--; 17 a[++r]=x; 18 } 19 pii top(){return a[l+1];} 20 void pop(){l++;} 21 }q; 22 int a[maxn]; 23 ll dp[maxn][maxn]; 24 int main() 25 { 26 scanf("%d%d%d",&n,&k,&x); 27 for(int i=1;i<=n;++i)scanf("%d",&a[i]); 28 if(n>=(x+1)*k) 29 { 30 puts("-1");exit(0); 31 } 32 for(int i=0;i<=n;++i) 33 for(int j=0;j<=x;++j)dp[i][j]=-(ll)1e17; 34 dp[0][0]=0; 35 for(int j=1;j<=x;++j) 36 { 37 q.init(); 38 q.push(mp(0,0)); 39 for(int i=1;i<=n;++i) 40 { 41 while(!q.empty()&&q.top().second<i-k)q.pop(); 42 int t=q.top().second; 43 if(dp[t][j-1]>=0)dp[i][j]=dp[t][j-1]+a[i]; 44 q.push(mp(dp[i][j-1],i)); 45 } 46 } 47 ll ans=0; 48 for(int i=n-k+1;i<=n;++i)ans=max(ans,dp[i][x]); 49 printf("%I64d\n",ans); 50 return 0; 51 }