首页 > 其他分享 >【最大子段和问题:不定长、定长、有长度上界】

【最大子段和问题:不定长、定长、有长度上界】

时间:2024-08-11 16:54:21浏览次数:7  
标签:cnt 前缀 子段 int sum ans 长度 不定

题目

思考

我由这道题想起了一系列问题:

最大连续子段和        贪心 \in O(n)

最大连续子段和,但是区间长度为m        前缀和 \in O(n)

最大连续子段和,但是区间长度小于等于m        我的思考是从贪心上面改 \in O(n)

错误代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5+10;
LL a[N]; 
int main()
{
    int n, m, cnt = 0;
    cin >> n >> m;
    LL ans = -1e9, sum = 0;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        sum += a[i], cnt++;
        if(sum > ans) ans = sum;
        if(sum < 0) sum = 0, cnt = 0;
        if(cnt >= m)
        {
            sum -= a[i-m+1];
        }
    }
    
    cout << ans;
    
    return 0;
}

正确代码

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int a[N], s[N];
int ms[N], h = 1, t = 0;

int main() {
    
    int n, m;
    cin >> n >> m;
    int ans = INT_MIN;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        s[i] = s[i-1] + a[i];
        
        int j = i-1; //j滞后i 1,因为s[i]不应该进入s[ms[h]]的最小值备选。对于每个s[i], 大小为m的范围指的是[i-m,i-1] = [j-m+1, j]
        while(h <= t && s[j] <= s[ms[t]]) t--; //队尾出
        ms[++t] = j; //队尾进
        if(ms[h] < j - m + 1) h++; //队头出
        ans = max(ans, s[i] - s[ms[h]]);
    }

    cout << ans;
    return 0;
}

感悟

正确代码将前缀和+二维搜索边界的问题转化为了——前缀和+单调队列的问题:

最大子段和 = max( s[ i ] - s[ j ] ) (s[ j ] 为 [ j-m+1, j ], j = i-1范围内的最小值)\in O(n)

难点在于单调队列覆盖的范围都会进入最值考虑,而对于每个s[i],s[i]是不进入最值考虑的(子段至少有一个数),因此i 要 比 j 大 1,i 参与最终前缀和计算, j 参与 单调队列的维护。

标签:cnt,前缀,子段,int,sum,ans,长度,不定
From: https://blog.csdn.net/m0_73669127/article/details/141105940

相关文章

  • strlen求字符串长度 模拟实现strlen函数 strcpy函数 模拟实现strcpy strcat函数 模拟
    文章目录1.1strlen求字符串长度1.2模拟实现strlen函数2.1strcpy函数2.2模拟实现strcpy3.1strcat函数3.2模拟实现strcat1.1strlen求字符串长度strlen是一个库函数所包含的头文件为#include<string.h>,这里我们可以在Cplusplus上找到strlen所包含的头文件以及strlen......
  • 中国式报表搞不定?这个神器让你事半功倍!
    一般的报表表头非常简单,没有斜线表头,也没有分层分组,但这样的报表提供的信息非常有限,通常需要几张表对照着一起看。 设想一下,如果你准备要制作一张年终汇总报表,而这张报表要求你将各种各样的数据都要集中在一张表上......难以想象其数据量之庞大+整理之困难!   如上图所......
  • 中国式报表搞不定?告诉你如何轻松解决
    中国式报表,顾名思义,是一种在中国企业中广泛使用的报表格式。这种报表通常格式复杂、数据量大、数据层次多,涵盖了从基本数据到高层分析的各个层面。每一个字段都可能代表着不同的含义,每一列数据都有着深厚的背景,这让很多报表工具望而却步。然而,要想在中国企业中高效工作,掌握中国式......
  • 织梦dede怎么修改关键字长度?
    dede文件修改默认关键字长度第1步:找到并打开dede后台目录下的article_edit.php和article_add.php文件。电脑维修技术网注:如果是修改专题认关键字的话,需要修改spec_add.php和spec_edit.php文件。第2步:在文件中搜索"keywords",找到“$keywords=trim(cn_substrR($keywords,60));......
  • 1.3 长度最小的子数组
    代码随想录的数组部分,废话不多说直接刷题!!!leetcode209长度最小的子数组给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其总和大于等于target的长度最小的子数组[numsl,numsl+1,…,numsr-1,numsr],并返回其长度。如果不存在符合条件的子数......
  • SOMEIP_ETS_002:数组长度过长
    测试目的:确保DUT在接收到的SOME/IP消息中数组长度超出实际数组长度时,能够返回错误消息。描述本测试用例旨在验证当DUT接收到一个声明数组长度超过其实际长度的SOME/IP消息时,DUT是否能够正确地返回错误消息(MALFORMED_MESSAGE)。测试拓扑:具体步骤:TESTER:创建SOME/IP消息,......
  • 子段和问题
    Abstract本文主要介绍各种序列子段和问题。P1最大子段和传送门Introduction首先来看一道经典例题,求一段序列的最大子段和Idea考虑动态规划,令dp[i]表示在取第i个数的情况下,前i个数所能得到的最大子段和,那么显然有dp[i]=max(dp[i-1]+a[i],a[i]),其中a[i]表......
  • 2024-07-31:用go语言,给定两个正整数数组arr1和arr2,我们要找到属于arr1的整数x和属于arr
    2024-07-31:用go语言,给定两个正整数数组arr1和arr2,我们要找到属于arr1的整数x和属于arr2的整数y组成的所有数对(x,y)中,具有最长公共前缀的长度。公共前缀是指两个数的最左边的一位或多位数字相同的部分。例如,对于整数5655359和56554来说,它们的公共前缀是565,而对于1223和434......
  • 2024-07-31:用go语言,给定两个正整数数组arr1和arr2,我们要找到属于arr1的整数x和属于arr
    2024-07-31:用go语言,给定两个正整数数组arr1和arr2,我们要找到属于arr1的整数x和属于arr2的整数y组成的所有数对(x,y)中,具有最长公共前缀的长度。公共前缀是指两个数的最左边的一位或多位数字相同的部分。例如,对于整数5655359和56554来说,它们的公共前缀是565,而对于1223和43456来说......
  • 最优 K 子段
    素数的密度约为ln(n),这就是说,1~n中素数的个数约为\(\frac{n}{ln(n)}\)观察你写出来的DP转移式,可以发现检查时没有必要DP,直接贪心就好了由于数据随机,最后十分钟“乱搞”两次成功过题,开心~点击查看代码#include<bits/stdc++.h>usingnamespacestd;intprime[20005],m;i......