BZOJ_2343_[Usaco2011 Open]修剪草坪 _單調隊列_DP
阿新 • • 發佈:2018-03-11
bsp long long bzoj main ans 單調隊列 題意 r++ pac
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); }
BZOJ_2343_[Usaco2011 Open]修剪草坪 _單調隊列_DP