1. 程式人生 > >bzoj2442[Usaco2011 Open]修剪草坪 單調隊列優化dp

bzoj2442[Usaco2011 Open]修剪草坪 單調隊列優化dp

php -m 不同的 mes put space 希望 open 最小值

2442: [Usaco2011 Open]修剪草坪

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1159 Solved: 593
[Submit][Status][Discuss]

Description


在一年前贏得了小鎮的最佳草坪比賽後,FJ變得很懶,再也沒有修剪過草坪。現在,
新一輪的最佳草坪比賽又開始了,FJ希望能夠再次奪冠。

然而,FJ的草坪非常臟亂,因此,FJ只能夠讓他的奶牛來完成這項工作。FJ有N
(1 <= N <= 100,000)只排成一排的奶牛,編號為1...N。每只奶牛的效率是不同的,
奶牛i的效率為E_i(0 <= E_i <= 1,000,000,000)。


靠近的奶牛們很熟悉,因此,如果FJ安排超過K只連續的奶牛,那麽,這些奶牛就會罷工
去開派對:)。因此,現在FJ需要你的幫助,計算FJ可以得到的最大效率,並且該方案中
沒有連續的超過K只奶牛。

Input


* 第一行:空格隔開的兩個整數N和K

* 第二到N+1行:第i+1行有一個整數E_i


Output


* 第一行:一個值,表示FJ可以得到的最大的效率值。

Sample Input

5 2
1
2
3
4
5

輸入解釋:

FJ有5只奶牛,他們的效率為1,2,3,4,5。他們希望選取效率總和最大的奶牛,但是
他不能選取超過2只連續的奶牛

Sample Output


12

FJ可以選擇出了第三只以外的其他奶牛,總的效率為1+2+4+5=12。

正難則反
考慮在每k個中有一個不選
設f[i]為到i位置合法且i不選,不選的牛價值之和的最小值
ans=sum-f[i](n-m<=i<=n)
轉移f[i]=a[i]+min(f[j]) (i-j<=m+1)
可以發現後面那個東西可以用單調隊列維護

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #define
N 100005 5 #define ll long long 6 using namespace std; 7 int n,m,a[N],q[N];ll sum,f[N]; 8 int main(){ 9 scanf("%d%d",&n,&m); 10 for(int i=1;i<=n;i++) 11 scanf("%d",&a[i]),sum+=a[i]; 12 int h=1,t=1; 13 for(int i=1;i<=n;i++){ 14 while(h<=t&&i-q[h]>1+m)h++; 15 f[i]=a[i]+f[q[h]]; 16 while(h<=t&&f[q[t]]>=f[i])t--; 17 q[++t]=i; 18 } 19 ll ans=f[n]; 20 for(int i=n-m;i<n;i++)ans=min(ans,f[i]); 21 cout<<sum-ans;return 0; 22 }

bzoj2442[Usaco2011 Open]修剪草坪 單調隊列優化dp