楼房重建
这一道题目稍微转换一下题意之后就可以知道需要维护一个斜率单调递增的序列(下文把每个点的斜率称为权值),这个就是单调队列的操作
所以动态维护权值单增(单减)序列可以像下面这么做
我们根据线段树“分而治之”的思想,用每一个节点维护相似的信息
维护什么呢?维护在这一个节点的代表区间中,以这一个节点所代表的区间的第一个点为开头的权值不下降序列的长度,以及这个节点所代表的区间的权值的最大值
那么查询的时候直接输出根节点的序列长度即可
修改的时候,先点修改到最低的叶子节点,那么合并怎么合并呢?
在合并的时候,父节点肯定会继承左子节点的序列(即左子节点的序列是父节点序列的左半部分),问题是右节点怎么办呢?
这个时候,我们要解决的问题是:在右子节点中寻找第一个权值比左子节点最大权值还要大的位置,并从这个位置开始所得到的不下降序列长度
我们就将其作为一个函数,尝试进行分而治之,即解决在当前节点中寻找第一个权值比给定权值还要大的位置,并从这个位置开始所得到的不下降序列长度
如果右子节点的左子节点的最大值比左子节点的最大值小,那么右子节点的左子节点的所有房子一定看不到,所以我们就可以递归查找右子节点的右子节点
如果右子节点的左子节点的最大值比左子节点的最大值大,可以想一下应该怎么做(具体见代码,这个很容易看懂)
时间复杂度为
注意这里一定要维护长度,所以才需要递归套递归导致
我还想了另一种方法,也很经典
用一颗线段树维护两个值,一个是区间最大值,一个是区间和,这里的和定义为当前节点所代表区间的每个点的贡献和,而每个点的贡献要么是
那么在修改一个点的时候,我们只讨论是增高的这种情况
如果增高的不够多(就是前面的最高的房子更高),那么更新一下区间最大值就好了,其他都不变
如果增高的足够多了,那么在修改最大值的同时,也要把这个点的贡献变为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构