首页 > 其他分享 >最大子段和以及拓展

最大子段和以及拓展

时间:2023-11-28 21:34:32浏览次数:24  
标签:le 最大 子段 int 拓展 队列 端点 区间 dp

无限制最长连续的子序列和

https://www.acwing.com/problem/content/description/1481/

dp[i]=max(dp[i-1]+a[i],a[i]);

最终结果也就是在dp数组线性扫描找出最大值
int pos=max_element(dp+1,dp+1+n)-dp;
cout<<dp[pos]<<" ";
dp[i]表示以序列中第i个数字结尾的最大子段和
转移方程思考:如果选第i-1个数,那么由dp[i-1]转移过来,如果不选第i-1个数,那么它只能自己一个人作为一个子段存在,因为必须以第i个数结尾。

在给的题目中,还要求给出具体是哪段子段和最大,也就是左端点和右端点。
在我的代码中,是先求出来最大值,然后再排序所有符合最大值的子段的,按照题目要求左端和右端尽可能的小。
但这样在空间和时间上都是不优的,应该在线性扫描的时候就去维护最大值,一旦可以更新,也就更新左右端点。

有长度限制最长连续的子序列和

类型:单调队列优化dp

随着见的题目越来越多,单调队列也用的越来越多,单调队列用于找某个连续窗口的找到某个性质最小/大值,将这个本身O(n)的过程优化成O(1)
https://www.acwing.com/solution/content/67527/
上面的链接是题解,借鉴一下,个人认为写的很清楚。
题目描述

给定一个长度为 \(n\) 的序列 \(a\),找出其中 元素总和最大 且 长度 不超过 \(m\) 的 连续子区间

分析

看到求一段 连续区间 的和的问题,会想到用 前缀和 进行优化,然后就是 枚举 区间的问题

暴力枚举 子区间是一种方法,但没有优化空间;因此不妨 枚举 子区间的 右端点

闫氏DP分析法

状态表示-集合 \(f_i\):以 \(i\) 为 右端点,长度 不超过 \(m\) 连续子区间

状态表示-属性 \(f_i\):区间的总和最大 \(Max\)

状态计算 \(f_i\):

\[f_i = \max\big\{{ s_i - s_j }\big\} \qquad (1 \le i - j \le m) \]

观察这个转移方程,首先这里的 \(j\) 是有范围的:\(i - m \le j \le i - 1\)

其次,\(s_i\) 作为一个常量,可以提到外面去:\(f_i = s_i - \min\big\{{ s_j }\big\} \qquad(1 \le i - j \le m)\)

从前向后 维护一个长度不超过 \(m\) 的区间的 最小值,就想到我们最熟悉的 滑动窗口模型

那么该状态 转移方程 就可以用 单调队列 进行优化了。这就是典型的应用场景,我们需要决策在当前m个j选哪一个j使得s[j]最小,用了单调队列维护我们就能快速知道,当前状态应该从哪一个状态转移过来最优。
Code

时间复杂度: \(O(n)\) (每个元素至多入队出队一次,每次转移又是 \(O(1)\) 的)

为了避免这个 高亮BUG,单调队列 q[] 改名为 que[]

由于这里 f[i] 没有相互依赖的关系,最后答案是统计所有 f[i] 的最大值

故我们直接用一个变量 res 来计算



using namespace std;

typedef long long LL;

const int N = 3e5 + 10;

int n, m;
LL s[N], que[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%lld", &s[i]), s[i] += s[i - 1];
//处理前缀和
    LL res = -1e18;
    int hh = 0, tt = 0; que[0] = 0;
    for (int i = 1; i <= n; i ++ )
    {
        while (hh <= tt && i - que[hh] > m) hh ++ ;
        res = max(res, s[i] - s[que[hh]]);
        while (hh <= tt && s[que[tt]] >= s[i]) tt -- ;
        que[ ++ tt] = i;
    }
    printf("%lld\n", res);
    return 0;
}

标签:le,最大,子段,int,拓展,队列,端点,区间,dp
From: https://www.cnblogs.com/mathiter/p/17863130.html

相关文章

  • 冒泡排序:要比较(二层循环)n*(n-1)(第一层循环)次,最大的在最后,最次大的在倒数第二,
    privatestatic voidsort(int[]w,intl,intr){//冒泡排序要比较n二层循环*(n-1)次,第一层循环      for(inti=r;i>l;i--){        for(intj=l;j<i;j++){          if(w[j]>w[j+1])          { ......
  • 电动车最大续航里程计算公式 All In One
    电动车最大续航里程计算公式AllInOne电动车&功率计算公式电功率计算公式P=W/T=U*I直流电功率计算公式(已知电压、电流时)P=U*IP=W/T推断出,续航时间=>T=W/P根据测试的车速和时间(载重量),推断出,最大续航里程S=V*Tdemos绿源S70电动......
  • 期望最大化(EM)算法:从理论到实战全解析
    本文深入探讨了期望最大化(EM)算法的原理、数学基础和应用。通过详尽的定义和具体例子,文章阐释了EM算法在高斯混合模型(GMM)中的应用,并通过Python和PyTorch代码实现进行了实战演示。关注TechLead,分享AI全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济......
  • 期望最大化(EM)算法:从理论到实战全解析
    本文深入探讨了期望最大化(EM)算法的原理、数学基础和应用。通过详尽的定义和具体例子,文章阐释了EM算法在高斯混合模型(GMM)中的应用,并通过Python和PyTorch代码实现进行了实战演示。关注TechLead,分享AI全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济......
  • NOIP2023 双序列拓展
    洛谷传送门首先\(x_1=y_1\)显然不合法。若\(x_1>y_1\)就把\(x,y\)全部取相反数,这样就只用考虑\(x_1<y_1\)的情况了。然后考虑一个\(O(nmq)\)的dp,设\(f_{i,j}\)为拓展\(X\)的前\(i\)个元素和\(Y\)的前\(j\)个元素是否可行。那么若\(x_i<y_j\)则......
  • 聪明办法学Python-2023-task04&拓展01
    参考视频链接:【条件】聪明办法学Python第二版_哔哩哔哩_bilibili​优雅代码编写指北_哔哩哔哩_bilibilitask04if语句ifstatementConditionalsMakeDecisionsif语句流程判断成立不成立一个例子:deff(x):print("A",end="")......
  • 2943. 最大化网格图中正方形空洞的面积
     简单模拟即可:classSolution{public:vector<int>findWordsContaining(vector<string>&words,charx){intn=words.size();vector<int>res;for(inti=0;i<n;i++){auto&word=wor......
  • 数据类型拓展
    整数拓展:进制二进制0b;八进制0;十进制;十六进制0x 十进制转二进制,将正的十进制除以二,得到商后再除以二,直到商为1或0时,然后各部余数填1,整数填0,然后倒着写出来,最后高位补零一个正的二进制的数转为负的只需要将该数的二进制码取反然后+1(补码)即可浮点拓展:浮点数一般都会存在舍入误差,所以......
  • AcWing 1128. 信使 (dij板子题 + 求花费最大的那个点的花费
    package算法提高课;importjava.util.Arrays;importjava.util.PriorityQueue;importjava.util.Scanner;publicclassacw1128{staticintn,m;staticint[]h,e,w,ne;staticint[]d;staticboolean[]st;staticintidx;staticclas......
  • 一个最大张角尺规可作性命题的分析与证明
    命题:在平面直角坐标系中,从x轴的上方任意取定不同两点M和N.则通过尺规作图一定可以找出x轴上的一点Q,使得MQN张角最大.分析与证明:先证明最大张角点的存在性.第一步:若最大张角点存在,考察其满足什么性质.如上图所示,直线AB为x轴,M和N是x轴上方不同两点.记M和......