首页 > 其他分享 >最大子序和问题

最大子序和问题

时间:2023-09-21 21:35:48浏览次数:36  
标签:ch 最大 int res 问题 le qmin 子序 dp

[HDU 1003] Max Sum

题意:给定你一个长度为 $ n $ 的序列 $ a_1, a_2, a_3, \cdot\cdot\cdot a_n $, 找出其中一段连续的子序列, 使得这段子序列的和最大。

思路:考虑 DP, 设 $ dp_i $ :以 $ a_i $ 结尾的最大子序和, 因为需要找连续的一段, 所以 $ dp_i = max(dp_{i - 1} + a_i, a_i) $, 即:如果 $ dp_{i - 1} > 0 $, 就将 $ dp_{i - 1} $ 加到 $ dp_i $ 里面。

点击查看代码
#include <bits/stdc++.h>

inline int read() {
    bool sym = false; int res = 0; char ch = getchar();
    while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
    return sym ? -res : res;
}

int main() {
    int T = read();

    for (int i = 1; i <= T; i++) {
        int n = read();
        std::vector<int> a(n + 1);
        std::vector<int> dp(n + 1);
        for (int j = 1; j <= n; j++) {
            a[j] = read();
        }
        for (int j = 1; j <= n; j++) {
            dp[j] = a[j];
        }
        int max = (int) -2e9, p = 1, l = 1, r = 1;
        for (int j = 1; j <= n; j++) {
            if (dp[j - 1] > 0) {
                dp[j] += dp[j - 1];
            } else {
                p = j;
            }
            if (dp[j] > max) {
                max = dp[j]; l = p; r = j;
            }
        }
        printf("Case %d:\n%d %d %d\n", i, max, l, r);
    }

    return 0;
}

接下来考虑一个新的问题:如果限制连续子序列的长度 $ \le m $, 此问题该如何求解?

[洛谷 P1714] 切蛋糕

思路:将问题转化为:对于任意的 $ i(1 \le i \le n) $, 找到一个 $ j(i - j \le m) $, 满足 $ \Sigma_{k = j}^i a_i $ 最大。若枚举终点 $ i $, 然后每一次向前检查 $ m $ 个数字, 那么时间复杂度为 $ O(nm) $, 对于 $ \le 5 \times 10^5 $ 的 $ n、m $, 这样的复杂度显然是无法接受的。考虑到枚举每一个终点 $ i $ 时, 只需要找到左边 $ 1 \sim m $ 范围内的前缀和的最小值(设前缀和数组为 $ sum_i $, 那么对于每一个位置 $ i $, 需要找到一个 $ j (i - j \le m) $, 满足 $ sum_i - sum_{j - 1} $ 最大), 这里可以用单调队列维护一个长度为 $ m $ 的滑动窗口。每个元素入队、出队一次, 总的时间复杂度为 $ O(n) $。

点击查看代码
#include <bits/stdc++.h>

inline int read() {
    bool sym = false; int res = 0; char ch = getchar();
    while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
    return sym ? -res : res;
}

int main() {
    int n = read(), m = read();
    std::vector<long long> p(n + 1);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &p[i]);
    }
    std::vector<long long> pref(n + 1);
    for (int i = 1; i <= n; i++) {
        pref[i] = pref[i - 1] + p[i];
    }
    std::deque<long long> qmin;
    long long max = pref[1];
    std::vector<long long> value(n + 1);
    for (int i = 1; i < n; i++) {
        while (qmin.size() && pref[i] <= pref[qmin.back()]) {
            qmin.pop_back();
        }
        qmin.push_back(i);
        if (i >= m) {
            while (qmin.size() && qmin.front() < i + 1 - m) {
                qmin.pop_front();
            }
        }
        value[i + 1] = pref[qmin.front()];
    }
    for (int i = 2; i <= n; i++) {
        max = std::max(max, pref[i] - value[i]);
    }
    printf("%lld\n", max);
    return 0;
}

标签:ch,最大,int,res,问题,le,qmin,子序,dp
From: https://www.cnblogs.com/LDUyanhy/p/17721007.html

相关文章

  • 关于mysql安装过程中的密码设置问题
    在使用setpassword=password("0000000000");更改密码时出现的ERROR1064(42000):YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtousenear'password("0000000000")......
  • linux中安装mysql过程中出现的某某包需要被依赖问题
    问题—— 原因,顺序错误 使用rpm安装MySQL,需要严格按照如下的执行顺序进行安装,如果顺序不对,会提示某某包需要被依赖。rpm-ivhmysql-community-common-8.0.34-1.el7.x86_64.rpmrpm-ivhmysql-community-client-plugins-8.0.34-1.el7.x86_64.rpmrpm-ivhmysql-communit......
  • docker搭建青龙面板及白屏问题解决方法
    最近也是想赚点小钱,搭建个青龙面包来挂脚本,但是在搭建过程中遇到过一些问题,所以记录下来。docker搭建青龙面板我这里是使用aliyun服务器进行搭建的,系统是centOS7.6版本。另外docker自行搜索安装即可。拉取青龙面板镜像远程登录服务器,输入命令拉取青龙镜像dockerpullwhyour......
  • 一些H5对接微信JSSDK的问题记录
    这里给大家分享我在实际生活中总结出来的一些知识,希望对大家有所帮助一.SDK引入这里提供两套引入流程,一套是vue2.0及其他h5项目,一套是vue3.0的引入流程不懂的也可以看我之前的一篇详细流程记录--微信调用jssdk全流程详解1.js引入直接在你的页面里引入js文件就行<scriptsr......
  • 解决WPF+Avalonia在openKylin系统下默认字体问题
    一、openKylin简介openKylin(开放麒麟)社区是在开源、自愿、平等和协作的基础上,由基础软硬件企业、非营利性组织、社团组织、高等院校、科研机构和个人开发者共同创立的一个开源社区,致力于通过开源、开放的社区合作,构建桌面操作系统开源社区,推动Linux开源技术及其软硬件生态繁荣发......
  • 解决天平秤球问题
    问题12个外观一致的小球,其中11个质量一致,1个质量不同,用一个天平,问最少能称几次能找到这个小球。解答思路1最先想到,用二分法,步骤如下:分两组,1-3、4-6分别上天平两侧;如果平衡,进行步骤2,否则进行步骤3说明1-6质量一致;将7-12重新编号为1-6,将1-6编号为7-12,进行步骤1如果1-3更重(1-......
  • 迁移虚拟机使用遇到的问题
    迁移背景本次在迁移前的主机系统为REDHAT8,每台机器配置了专门的ip+搭建好yum环境迁移时虚拟机版本需要统一如果不统一,需要在.vmx文件中修改 2.虚拟网络编辑器要与迁移前保持一致 3.搭建好yum路径要与迁移前路径保持一致4.如果开机后ifconfig不显示,需要使用nmclinon......
  • 记录一次:Winform的控件的Visible属性异常问题
    一:背景1.讲故事有一次同事找到我,说以下代码中:btnPlanAppend控件:客户电脑显示正常、开发者电脑调试时无法显示btnAppend可以在界面中显示出来btnPlanAppend控件在界面上就是不显示privatevoidCheck_Privilege(){stringsPrivilege=ClientUtils.GetPrivilege(g_sU......
  • RHEL5 上安装 oracle10g 中出现的问题记录
    1.不能启动安装界面运行runInstaller提示信息类似如下:xlib:connectionto"localhost:0.0"refusedbyserverxlib:clientisnotauthorizedtoconnecttoserver Exceptioninthread"main"java.lang.InternalError:can'tconnecttox11windowserverusing......
  • LeetCode53.最大子数组和
    要求最大连续子数组的和,可以这样考虑,比如现在我想求下标 i~j,i<j 这一范围内子数组的和,那么我可以分别先求出 0~i-1 范围和 0~j 范围两个子数组的和,可得Sum[i~j]=Sum[0~j]-Sum[0~i-1] ,这就是本题解法的核心思想。解法详细描述:先从下标0开始,遍历 nums 数组,求出到当前下标......