单调队列优化DP——修建草坪

修建草坪

在一年前赢得了小镇的最佳草坪比赛后,FJ 变得很懒,再也没有修剪过草坪。

现在,新一轮的最佳草坪比赛又开始了,FJ 希望能够再次夺冠。

然而,FJ 的草坪非常脏乱,因此,FJ 只能够让他的奶牛来完成这项工作。

FJ 有 NN 只排成一排的奶牛,编号为 11 到 NN。

每只奶牛的效率是不同的,奶牛 ii 的效率为 EiEi。

编号相邻的奶牛们很熟悉,如果 FJ 安排超过 KK 只编号连续的奶牛,那么这些奶牛就会罢工去开派对。

因此,现在 FJ 需要你的帮助,找到最合理的安排方案并计算 FJ 可以得到的最大效率。

注意,方案需满足不能包含超过 KK 只编号连续的奶牛。

输入格式
第一行:空格隔开的两个整数 NN 和 KK;

第二到 N+1N+1 行:第 i+1i+1 行有一个整数 EiEi。

输出格式
共一行,包含一个数值,表示 FJ 可以得到的最大的效率值。

数据范围
1 N 1 0 5 , 1 N 1 0 5 , 1≤N≤10^5 ,1≤N≤10^5,
0 E i 1 0 9 , 0 E i 1 0 9 0≤E_i≤10^9,0≤E_i≤10^9
输入样例:
5 2
1
2
3
4
5
输出样例:
12
样例解释
FJ 有 5 只奶牛,效率分别为 1、2、3、4、5。

FJ 希望选取的奶牛效率总和最大,但是他不能选取超过 2 只连续的奶牛。

因此可以选择第三只以外的其他奶牛,总的效率为 1 + 2 + 4 + 5 = 12。

今天电脑放到百脑会去修了,在网吧写的暂时不写公式上去。明天电脑拿回来再把过程和公式写上来。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+7;
int q[N],s[N],f[N];
int g(int x)
{
    if(!x) return 0;
    return f[x-1]-s[x];
}
signed main()
{
    int n,m; cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        s[i]+=s[i-1];
    }
    int h=0,t=0;
    for(int i=1;i<=n;i++){
        while(q[h]<i-m) h++;
        f[i]=max(f[i-1],g(q[h])+s[i]);
        while(h<=t&&g(q[t])<=g(i)) t--;
        q[++t]=i;
    }
    cout<<f[n]<<endl;
}
发布了92 篇原创文章 · 获赞 6 · 访问量 1153

猜你喜欢

转载自blog.csdn.net/weixin_42979819/article/details/103979899