当前位置: 首页 > article >正文

一、基础数据结构——2.队列——3.双端队列和单调队列2

参考资料:《算法竞赛》,罗勇军 郭卫斌 著
本博客作为阅读本书的学习笔记,仅供交流学习。
建议关注 罗勇军老师博客

3. 单调队列与最大子序和问题

不限制子序列长度问题——贪心法或动态规划

HDOJ 1003 MAX SUM

Max Sum Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/32768 K (Java/Others)

Problem Description
Given a sequence a[1],a[2],a[3]…a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.

Input

The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).

Output
For each test case, you should output two lines. The first line is “Case #:”, # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.

Sample Input
2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5

Sample Output
Case 1: 14 1 4
Case 2: 7 1 6

Author
Ignatius.L

  1. 贪心法
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x7fffffff;

int main() {
    int t; cin>>t;//测试用例个数
    for (int i = 1; i <= t; ++i) {
        int n; cin>>n;
        int maxsum = -INF;//最大子序和,初始设为一个最小的int负数
        int start = 1, end=1, p=1; //起点,终点,扫描位置
        int sum=0;
        for (int j = 1; j <= n; ++j) {
            int a; cin>>a; sum+=a;//读入一个元素,累加
            if (sum>maxsum){maxsum=sum;start=p;end=j;}
            if (sum<0){//扫描到j时,若前面的最大子序和是负数,从下一个重新开始求和
                sum=0;
                p=j+1;
            }
        }
        printf("Case %d:\n",i);
        printf(" %d %d %d\n",maxsum,start,end);
        if (i!=t) cout<<endl;
    }
    return 0;
}
  1. 动态规划
#include <bits/stdc++.h>
using namespace std;
int dp[100005];//dp[i]:以第i个数为结尾的最大值
int main(){
    int t; cin>>t;//测试用例个数
    for (int k = 1; k <= t; ++k) {
        int n; cin>>n;
        for (int i = 1; i <= n; ++i) cin>>dp[i];//用dp[]存储数据a[]
        int start=1, end=1, p=1;//起点,终点,扫描位置
        int maxsum = dp[1];
        for (int i = 2; i <= n; ++i) {
            if (dp[i-1]+dp[i]>=dp[i])//转移方程dp[i]=max(dp[i-1]+a[i],a[i])
                dp[i]=dp[i-1]+dp[i];//dp[i-1]+a[i]比a[i]大
            else p=i;//a[i]更大,则dp[i]=a[i]
            if (dp[i]>maxsum){//dp[i]更大
                maxsum=dp[i];start=p;end=i;//p开始,i结尾
            }
        }
        printf("Case %d:\n",k);
        printf(" %d %d %d\n",maxsum,start,end);
        if (k!=t) cout<<endl;
    }
    return 0;
}

限制子序列长度问题——单调队列

#include <bits/stdc++.h>
using namespace std;
deque<int> dq;
int s[100005];
int main(){
    int n,m;scanf("%d %d",&n,&m);
    for (int i = 1; i < n; ++i) scanf("%lld",&s[i]);
    for (int i = 1; i < n; ++i) s[i]=s[i-1]+s[i];//计算前缀和
    int ans = -1e8;
    dq.push_back(0);
    for (int i = 1; i <= n; ++i) {
        while(!dq.empty()&&dq.front()<i-m) dq.pop_front();//队头超过m范围:删头
        if (dq.empty()) ans = max(ans,s[i]);
        else ans= max(ans,s[i]-s[dq.front()]);//队头就是最小的s[k]
        while(!dq.empty()&&s[dq.back()]>=s[i]) dq.pop_back();//队尾大于s[i]:去尾
        dq.push_back(i);
    }
    printf("%d\n",ans);
    return 0;
}

http://www.kler.cn/news/235010.html

相关文章:

  • 学习Android的第十天
  • JVM的主要组成部分,以及它们的作用。JVM中的内存区域有哪些,它们各自的作用是什么?什么是Java的堆内存,它如何影响程序的性能?
  • 鸿蒙harmony--TypeScript对象详解
  • Android录音功能的实现及踩坑记录
  • BIO、NIO、Netty演化总结
  • JavaScript DOM 变动观察器(Mutation observer)
  • DataBinding源码浅析---初始化过程
  • python coding with ChatGPT 打卡第20天| 二叉搜索树:搜索、验证、最小绝对差、众数
  • GPT-4模型的创造力
  • 蓝桥杯备赛Day9——链表进阶
  • Ps:直接从图层生成文件(图像资源)
  • 《CSS 简易速速上手小册》第10章:未来的 CSS(2024 最新版)
  • 【MySQL】-21 MySQL综合-8(MySQL默认值+MySQL非空约束+MySQL查看表中的约束)
  • Ainx-V0.2-简单的连接封装与业务绑定
  • Could not connect to Redis at 127.0.0.1:6379:由于目标计算机积极拒绝,无法连接...问题解决方法之一
  • leaflet 显示自己geoserver发布的中国地图
  • WordPress修改所有用户名并发送邮件通知的插件Easy Username Updater
  • vue双向绑定的原理
  • CTF-PWN-沙箱逃脱-【侧信道爆破】(2021-蓝帽杯初赛-slient)
  • 【开源】基于JAVA+Vue+SpringBoot的实验室耗材管理系统
  • ERROR: Could not build wheels for roslz4
  • PMP-情景模拟学习法-识别时间点
  • 2.11作业
  • 图灵日记--MapSet字符串常量池反射枚举Lambda表达式泛型
  • Pandas数据预处理之数据标准化-提升机器学习模型性能的关键步骤【第64篇—python:数据预处理】
  • 深入探索Flex布局:从基础到实战,附带抖音解决方案案例分析
  • C++提高编程(黑马笔记)
  • Jedis
  • HarmonyOS 横屏调试与真机横屏运行
  • Spring Boot生成二维码的两种实现方式