CF - 100513F Ilya Muromets(dp)

本文深入解析了一个在NEERC比赛中出现的签到题,初看上去似为贪心问题,实则巧妙地利用了动态规划(DP)策略。文章详细阐述了解题思路,包括定义状态数组d[i]和f[j],以及如何通过枚举求解最大值的过程。通过实例分析,旨在帮助读者掌握如何在看似简单的题目中发现并应用复杂算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是NEERC比赛重现的签到水题,做的时候以为是贪心,各种死在最后一组数据。


看了别人的代码才知道是dp。


用d[ i ]表示前i个元素中连续k个元素的最大和。

用f[ j ]表示后n-j+1个元素中连续k个元素的最大和。

然后枚举d[ i ] +  f[ i + 1 ]求最大值。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

typedef long long LL;
LL arr[200000+100], sum[200000+100];
LL d[200000+100], f[200000+100];

int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    for(int i=1; i<=n; i++)
    {
        scanf("%I64d", &arr[i]);
        sum[i]=sum[i-1]+arr[i];
    }
    for(int i=1; i<=n; i++)
        d[i]=max(d[i-1], sum[i]-sum[max(0, i-k)]);
    for(int i=n; i>=1; i--)
        f[i]=max(f[i+1], sum[min(n, i+k-1)]-sum[i-1]);
    LL ans=0;
    for(int i=1; i<=n; i++)
        ans=max(ans, d[i]+f[i+1]);
    printf("%I64d\n", ans);

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值