动态规划_基础_任意子区间序列求和问题_滑动窗口解法_多种思路_分治思想演变

题目描述

给出一段序列,选出其中连续且非空的一段使得这段和最大。

输入描述

第一行是一个正整数 N ( 1 ≤ N ≤ 200000 ) ,表示了序列的长度。

接下来的 N 行包含 N 个绝对值不大于 10000 的整数 A [ i ] ,描述了这段序列。

输出描述

仅包括 1 个整数,为最大的子段和是多少,子段的最小长度为 1 。

样例输入

7
2
-4
3
-1
2
-4
3

样例输出

4

Hint

Origin: Sidney
Edit by stdKonjac in 2020

解题思路:

关于求子区间求和的问题,现在已经有很多套路,比如线段树和树状数组,因为这俩都是通过子区间划分后自定向下形成的树。但是毕竟是动态规划专题,还是不要背模板了。

说到划分,最著名的题就是整数划分问题,只是整数划分问题是从一个整数划到区间长度=1-n,而现在这个问题是从区间求和返回整数,相当于一个逆过程,

那么划分嘛,反过来就是归并,总体还是分治思想啊,所以,先复习一下分治法最有名的归并排序算法,

贴个链接:https://www.cnblogs.com/KID-yln/p/12636211.html

和归并一样,现在有两种思路,

  • 第一种直接对区间划分,整体使用搜索递归,自顶向下,得到划分的区间脚标,然后返回一个求和,最好是能实现之前小期间的和能被后来的大区间利用到
  • 第二种直接规定区间长度可为1-n,利用循环,仿照非递归实现的归并算法,每次得到脚标的起点和终点然后求和,具体优化可以仿照滑动窗口

因为是动态规划—递推专题,先说一下第二种做法:

仿照滑动窗口,规定一个窗口大小从1-n的窗口,每次移动一个位置就一加一减,

进一步最好区间长度i从大到小遍历,并且把第i项第一个求和存下来,后面使用,

运算次数不超过O(n^2),假设CPU运算次数为10^(-10)s一次,总耗时大概不会超过1s,有点勉强,可以试一试

(依照CPU i5 8400循环做 i-- ; 10亿次大概要1.2秒左右(10 0000 0000 一次减 1 减 10亿次到 0为止,该时间为循环延时时间+运算时间,循环延时时间占大头)

试了以下,运气很好,过了,,不到100ms,不知道是不是cpu比较快

以下为代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 //#include <cstring>
 4 #include <algorithm>
 5 //#include <numeric>
 6 using namespace std;
 7 typedef long long ll;
 8 const int M=2*1e5+10;
 9 int n;
10
11 ll a[M];
12
13 ll sum=0;
14 ll S(int from,int to) {
15     ll t=0;
16     for(int i=from; i<=to; i++)t+=a[i];
17     return t;
18 }
19
20 void f() {
21     int n1=n;
22     ll sum1=S(1,n);
23     sum=sum1;
24     while(n1) {
25         int l=0;
26         int r=1+n1-1;
27         sum1-=a[r];
28         ll ans=sum1;
29         while(r<=n) {
30             ans-=a[l];
31             ans+=a[r];
32             sum=max(sum,ans);
33             //printf("%lld ",ans);
34             l++;
35             r++;
36         }
37         //puts("");
38         n1--;
39     }
40     printf("%lld\n",sum);
41 }
42
43
44
45 int main() {
46     scanf("%d",&n);
47     for(int i=1; i<=n; i++)scanf("%lld",&a[i]);
48     a[0]=0;
49     f();
50
51
52     return 0;
53 }

现在回头来说一下第一种做法:

如果直接递归,主要可以利用循环1-n,内套一个栈,设置栈深,每种情况都重新算一次,

总共有n(n+1)/2次求和,运算次数达到了Σ(n-i)*i => O(n^3)看这个数量级为200000,指定TE,

那么想要优化就需要简化运算次数,至少需要利用到之前的求和,保存之前的求和值作为节点,那其实就是建—线段树OR树状数组—然后求某些分支节点的和,

其实这也是分治,只不过是把分治的内容化成了一棵树,数量级约为O(n*logn);

(占个坑,后面补上树状数组/线段树的做法)

原文地址:https://www.cnblogs.com/KID-yln/p/12536379.html

时间: 2024-11-05 17:32:17

动态规划_基础_任意子区间序列求和问题_滑动窗口解法_多种思路_分治思想演变的相关文章

蓝桥杯基础练习题1(序列求和)

/* 问题描述 求1+2+3+...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+2+3+...+n的值. 样例输入 4 样例输出 10 样例输入 100 说明:有一些试题会给出多组样例输入输出以帮助你更好的做题. 一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低. 样例输出 5050 数据规模与约定 1 <= n <= 1,000,000,000. 说明:请注意这里

python基础教程_学习笔记8:序列_练习与总结_1

序列_练习与总结 每次处理一个字符 任务: 用每次处理一个字符的方式处理字符串. 方案: 可以创建一个列表,列表的子项是字符串的字符.python实际上并没有一个特别的类型来对应"字符"并以此和字符串区分开来.可以调用内建的list,用字符串作为参数: thelist=list(thestring) 也可以不创建一个列表,直接用for语句完成对该字符串的循环遍历: for c in thestring: do_something_with(c) 或者使用列表推导中的for来遍历: re

python基础教程_学习笔记2:序列-2

序列-2 通用序列操作 序列相加 通过加号对列表进行连接操作: 列表 >>> [1,3,4]+[2,5,8] [1, 3, 4, 2, 5, 8] 字符串 >>> '134'+'258' '134258' 元组 >>> (1,2,3)+(2,5,8) (1, 2, 3, 2, 5, 8) 元素数据类型不同的列表 >>> [[1,3],[3,9]]+[[2,2],'abc'] [[1, 3], [3, 9], [2, 2], 'abc'

Swift教程_基础技术_获取当前日期时间、日期时间格式化及转换

Swift教程_基础技术_类型转换(父子类转换:Int.Double.String转换) Swift教程_基础技术_获取当前日期时间.日期时间格式化及转换 1.获取当前日期时间 var nowDate = NSDate() var formatter = NSDateFormatter() formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" var dateString = formatter.stringFromDate(nowDate) pri

第一天的代码练习_基础

//第一天的内容包括JAVA环境配置,数据类型的讲解,数据类型的运算.在环境配置中,要求在 cmd命令窗口下,在任何文件目录下,输入javac.exe,都能够出现正确的显示结果--就需要在环境变量 中设置 public class Test{      public static void main(String[] args){        //不能使用保留字.关键字       /*       变量定义的格式 :数据类型 变量名=初始化值       变量必须先赋值,后使用       

微信小程序_基础组件大全

微信小程序_基础组件 微信小程序为小程序开发者提供了一系列小程序基础组件,开发者可以通过组合这些小程序基础组件进行微信小程序的快速开发. 微信小程序组件是什么?微信小程序组件怎么用? 小程序组件是视图层的基本组成单元.小程序组件自带一些功能与微信风格的样式.一个小程序组件通常包括开始标签和结束标签,属性用来修饰这个组件,内容在两个标签之内. <tagname property="value"> Content goes here ... </tagename>

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

Oracle实践--PL/SQL基础之同义词和序列

PL/SQL基础入门之同义词和序列             PL/SQL:过程语言(Procedure  Language)和结构化语言(Structured Query Language)结合而成的编程语言,是对SQL的扩展,支持多种数据类型,如大对象和集合类型,可使用条件和循环等控制语句,可创建存储过程,程序包和触发器等,给sql语句的执行添加程序逻辑,与Oracle服务器和Oracle工具紧密集成,具有可移植性,灵活性和安全性. 同义词: /*     同义词:现有对象的一个别名: