两个和最大的区间(线段树+单调栈+dp)
胜哥投喂的一道面试题
题意:有一个环形数组,找出两个不重叠的子串,是的这两个区间内所有的数加起来的和最大。
数据范围:
思路:看到环形数组而且要选取一段长度为不超过的区间,所以不难想到要断环为链来处理。而想要快速的求出区间和,就需要借助前缀和来实现的计算出区间和是多少。这样我们的预处理就可以写出来了。
接下来我们就需要考虑区间和最大的问题,连续的一段区间最大和有两种方式来实现:
①直接,考虑以结尾的一段连续的区间,表示这个区间的最大和是多少,那么不难写出状态转移方程,这个表示的意思就是如果当前的值就是最大的,那就不需要从上一个状态转移过来,不然的话就在前一次的状态基础上加上当前的值,时间复杂度是。
②因为求一段连续区间的和可以转化成,那么要求出区间和的最大值,就需要让的值最小,那么就需要去动态的维护出来,所以就需要去考虑一个具有单调性的数据结构单调栈来维护出之前的最小值,时间复杂度
对于本题而言,因为我们有一个额外的限制条件,区间长度不能超过,所以不能单纯的用来对最大子段和来求解,考虑用单调栈+dp来求解.单调栈存下前个区间的最小前缀和,来表示以结尾的最大子段和,状态转移方程为:因为每一次单调栈栈顶的值都是要给下一次状态转移的方程用的,所以应该先状态转移求出以结尾的最大子段和,再去维护出之间的最小前缀和。
这样就求出了最大子段和,但是这个做法对于本题来说是不可取的,因为不可以单纯的认为最大子段和+次大子段和就是最后的答案,如果一段区间的数是...xx..xxx
这样的(xxx是我们要拿走的),这两个区间的和不一定是最大的,但是最后他俩加起来的和却是最大的,这就需要最后遍历一遍所有的长度为的区间将所有的情况都考虑进去。基于此需要同时存下左右区间的端点,而右端点就是,所以只需要在数组维护最大子段和的同时存下来区间的左端点,就可以了。
做完了上面的操作后,就是求答案的过程了。因为在遍历所有区间的时候,只能知道长度为的区间的某一段xxx
另外一段xxx
就需要剩下的或者区间去找,这个时候就不好再用原先的了.因为线段树可以维护出某一段区间的最大子段和,那么可以一开始就将数组建树.
在查找第二段区间最大的时候,直接在线段树上去查找就好了,这样就找出了两个不重叠的区间,使得和最大.
__EOF__

本文链接:https://www.cnblogs.com/Haven-/p/16733058.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现