P2034选择数字题解

Posted sky-zxz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2034选择数字题解相关的知识,希望对你有一定的参考价值。

题目链接:在这里~

题目描述:

给定一行n个非负整数a[1]..a[n]。现在你可以选择其中若干个数,
但不能有超过k个连续的数字被选择。你的任务是使得选出的数字的和最大。

输入格式:

 

第一行两个整数n,k

以下n行,每行一个整数表示a[i]。

 

输出格式:

输出一个值表示答案。

思路:考虑反面,不能有超过k个连续的数字被选,等价于连续的k+1个数字中必须删一个,考虑如何去删数字,f[i]表示删了第i个数字的最小代价,f[i]可由(i-k-1)--->(i-1)转移过来,即在i前面的k+1个数字间,必须删一个,且 当前决策对后面无影响。n=1e5,O(n^2)的算法是过不去的,所以可以单调队列优化。

 

代码:

 

#include<iostream> 
#include<cstdio>
#include<cstring>
#include<algorithm>
#define R register
#define ll long long int 
using namespace std;
const int N=1e5+5;
ll n,k,a[N],f[N],Min=1e16,fir=1,x[N],ans,head=1,tail=0;
int main(){
    scanf("%lld%lld",&n,&k);
    for(R int i=1;i<=n;++i){
    scanf("%lld",&a[i]);
    ans+=a[i];f[i]=Min;
    }
    f[0]=0;//第i个被删的最小代价
    for(R int i=1;i<=n;++i){
        if(i<=k+1)
        f[i]=a[i];
        else
        f[i]=f[x[head]]+a[i];
        while(head<=tail&&x[head]<i-k)head++;
        while(head<=tail&&f[x[tail]]>f[i])tail--;
        x[++tail]=i;
    }
    for(R int i=n;i>=n-k;--i)
    Min=min(Min,f[i]);
    printf("%lld",ans-Min);
    return 0;
}

 

以上是关于P2034选择数字题解的主要内容,如果未能解决你的问题,请参考以下文章

luogu P2034 选择数字 单调队列优化dp 脑残行为,导致wa了很多遍

根据在 Spinner 中选择的数字,相同的片段应该出现在另一个之下。如何?

VSCode自定义代码片段——CSS选择器

VSCode自定义代码片段6——CSS选择器

FJUT 奇怪的数列(线性选择算法)题解

10个JavaScript代码片段,使你更加容易前端开发。