BZOJ_2343_[Usaco2011 Open]修剪草坪 _單調隊列_DP


BZOJ_2343_[Usaco2011 Open]修剪草坪 _單調隊列_DP

題意:

N頭牛,每頭牛有一個權值,選擇一些牛,要求連續的不能超過k個,求選擇牛的權值和最大值

 

分析:

先考慮暴力DP,f[i] = f[j] + s[i]-s[j+1] (i-j-1<=k 1<=j<i)

意思是我們j+1不要,要j+2到i這部分

發現可以用單調隊列優化一下

維護一個單調遞減的單調隊列,比較時用f[i]-s[i-1]比較

 

代碼:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 100050
#define LL long long
int n,a[N],Q[N],l,r,k;
LL s[N],f[N],ans;
int main(){
scanf("%d%d",&n,&k);
int i;
for(i = 1;i <= n;i++){
scanf("%d",&a[i]);
s[i] = s[i - 1] + a[i];
}
r = 1;
for(i = 1;i <= k;i++){
f[i] = s[i];
while(l < r&& f[i] - s[i + 1] >= f[Q[r - 1]] - s[Q[r - 1] + 1]) r--;
Q[r++] = i;
ans = max(ans,f[i]);
}
for(i = k + 1;i <= n;i++){
while(l < r&& i - Q[l] - 1 > k) l++;
f[i] = f[Q[l]] - s[Q[l] + 1] + s[i];
while(l < r&& f[i] - s[i + 1] >= f[Q[r - 1]] - s[Q[r - 1] + 1]) r--;
Q[r++] = i;
ans = max(ans,f[i]);
// printf("%lld\n",f[i]);
}
printf("%lld\n",ans);
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com