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

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

隊列 isp 距離 ++ 奶牛 efi 能夠 輸入 最小

2442: [Usaco2011 Open]修剪草坪

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1118 Solved: 569
[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。

HINT

Source

Gold

考慮求反過來的最小值,即選一些牛不選,兩個牛之間的距離不能超過m的最小值。

顯然用單調隊列維護即可。

技術分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define LL long long
 8 using namespace std;
 9 int n,m;
10 LL a[100005];
11 LL f[100005];
12 struct data {
13     LL val,w;
14 }q[100005
]; 15 int main(){ 16 LL sum=0; 17 scanf("%d%d",&n,&m); 18 for(int i=1;i<=n;i++){scanf("%lld",&a[i]);sum+=a[i];} 19 int h=0,t=1; 20 q[0].w=0;q[0].val=0; 21 for(int i=1;i<=n;i++) { 22 while(h<t&&q[h].w<i-m-1) h++; 23 f[i]=q[h].val+a[i]; 24 while(f[i]<q[t-1].val&&h<t) t--; 25 q[t++]=(data){f[i],i}; 26 } 27 LL ans=1LL<<60; 28 for(int i=n;i>=n-m;i--) ans=min(ans,f[i]); 29 printf("%lld",sum-ans); 30 return 0; 31 }
View Code

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