1. 程式人生 > >Codeforces 1077F2 Pictures with Kittens (hard version)(DP+單調佇列優化)

Codeforces 1077F2 Pictures with Kittens (hard version)(DP+單調佇列優化)

題目連結: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 < pair<ll,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(make_pair(0,0)); 23 for(int i=1;i<=n;i++){ 24 while(!q.empty()&&q.front().second<i-k) q.pop_front(); 25 dp[i][j]=q.front().first+a[i];
26 while(!q.empty()&&q.back().first<=dp[i][j-1]) q.pop_back(); 27 q.push_back(make_pair(dp[i][j-1],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\n",ans); 36 return 0; 37 }
View Code