题目链接:Pictures with Kittens (hard version)
题意:给定n长度的数字序列ai,求从中选出x个满足任意k长度区间都至少有一个被选到的最大和。
题解:数据量5000,O(n^3)的DP不适用。需要加个单调队列优化。
注意每次是从$[i-k,i)$区间,选择加上ai。每次清空双向队列。
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 typedef long long ll; 9 const int N=5000+10; 10 ll a[N],dp[N][N],ans=-1e18; 11 deque <int> q; 12 13 int main(){ 14 int n,k,x; 15 scanf("%d%d%d",&n,&k,&x); 16 for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 17 for(int i=0;i<=n;i++) 18 for(int j=0;j<=n;j++) 19 dp[i][j]=-1e18; 20 dp[0][0]=0; 21 for(int j=1;j<=x;j++){ 22 q.push_back(0); 23 for(int i=1;i<=n;i++){ 24 while(!q.empty()&&q.front()<i-k) q.pop_front(); 25 dp[i][j]=dp[q.front()][j-1]+a[i]; 26 while(!q.empty()&&dp[q.back()][j-1]<=dp[i][j-1]) q.pop_back(); 27 q.push_back(i); 28 } 29 q.clear(); 30 } 31 32 for(int i=n-k+1;i<=n;i++) ans=max(ans,dp[i][x]); 33 if(ans<0) ans=-1; 34 35 printf("%lld ",ans); 36 return 0; 37 }