线段树维护最大子段和及其类似问题

news/2024/12/4 22:57:28/文章来源:https://www.cnblogs.com/zphh/p/18587440

引入

link。

我们可以分析出上题就是带修改的最大子段和。

遇到这种类型的题目应该想到用线段树。

实现

对于原数列,先建起一棵线段树,每个节点包含 最大前缀、最大后缀、最大字段和、区间和 信息。

当你明确一道题是线段树时,要先思考 pushuppushdown 怎么写,因为剩下的都是差不多的。 —— jzp.

因为本题是单查,没有 pushdown,就先考虑 pushup 怎么写:

  • 最大前缀只可能是左儿子的最大前缀或是左儿子的和加上右儿子的最大前缀,即 \(maxl_i = \max\{maxl_l, sum_l + maxl_r\}\)
  • 最大后缀同理,\(maxr_i = \max\{maxr_r, sum_r, maxr_l\}\)
  • 最大子段和就是左儿子最大子段和或右儿子最大子段和或左儿子最大后缀加右儿子最大前缀,即 \(maxs_i = \max\{maxs_l, maxs_r, maxr_l + maxl_r\}\)
  • 区间和很简单,不赘述。
void pushup(int id) {sum(id) = sum(ls) + sum(rs);maxl(id) = max(maxl(ls), sum(ls) + maxl(rs));maxr(id) = max(maxr(rs), sum(rs) + maxr(ls));maxs(id) = max(max(maxs(ls), maxs(rs)), maxr(ls) + maxl(rs));
}

那么对于每一次询问,我们找到线段树上的左右端点 \(l\)\(r\) 对应的两点 \(p_l\)\(p_r\)

当我们从上往下爬树爬到 \(k = LCA(p_l, p_r)\) 时,\(l\)\(r\) 就会分开为两个区间。

此时答案有几种可能:

  • \(l \le r \le m\),其中 \(m\) 为该区间的中间点,此时递归左侧得到答案。
  • \(m \lt l \le r\),此时递归右侧得到答案。
  • \(l \le m \lt r\),此时合并两次得到的答案。

以上三者取最大值返回。

这跟 cdq 分治的思想有异曲同工之妙。

\(l\)\(r\) 并没有分叉时,就直接走下去即可。

那么此时查询也可以顺利地写出来了。

segment query(int id, int lft, int rht, int l, int r) {	// 这里用 segment 作为返回值是因为每层递归都需要用到下一层递归的结果if (l <= lft && rht <= r) return seg[id];int mid = (lft + rht) >> 1;if (r <= mid) return query(ls, lft, mid, l, r);if (l > mid) return  query(rs, mid + 1, rht, l, r);segment a = query(ls, lft, mid, l, r), b = query(rs, mid + 1, rht, l, r), t;t.sum = a.sum + b.sum;t.maxl = max(a.maxl, a.sum + b.maxl);t.maxr = max(b.maxr, b.sum + a.maxr);t.maxs = max(max(a.maxs, b.maxs), a.maxr + b.maxl);return t;
}

整体代码:

struct segment_tree {#define ls (id << 1)#define rs (id << 1 | 1)#define sum(id) seg[id].sum#define maxl(id) seg[id].maxl#define maxr(id) seg[id].maxr#define maxs(id) seg[id].maxsstruct segment {int maxl, maxr;int sum, maxs;} seg[N << 2];void pushup(int id) {sum(id) = sum(ls) + sum(rs);maxl(id) = max(maxl(ls), sum(ls) + maxl(rs));maxr(id) = max(maxr(rs), sum(rs) + maxr(ls));maxs(id) = max(max(maxs(ls), maxs(rs)), maxr(ls) + maxl(rs));}void build(int id, int lft, int rht) {if (lft == rht) {sum(id) = a[lft];maxl(id) = maxr(id) = maxs(id) = a[lft];return;}int mid = (lft + rht) >> 1;build(ls, lft, mid), build(rs, mid + 1, rht);pushup(id);}void change(int id, int lft, int rht, int x, int v) {
//		if (lft > x || rht < x) return;if (lft == rht) {
//			a[lft] = v;sum(id) = v;maxl(id) = maxr(id) = maxs(id) = v;return;}int mid = (lft + rht) >> 1;if (x <= mid) change(ls, lft, mid, x, v); else change(rs, mid + 1, rht, x, v);pushup(id);}segment query(int id, int lft, int rht, int l, int r) {
//		if (lft > r || rht < l) return ;if (l <= lft && rht <= r) return seg[id];int mid = (lft + rht) >> 1;if (r <= mid) return query(ls, lft, mid, l, r);if (l > mid) return  query(rs, mid + 1, rht, l, r);segment a = query(ls, lft, mid, l, r), b = query(rs, mid + 1, rht, l, r), t;t.sum = a.sum + b.sum;t.maxl = max(a.maxl, a.sum + b.maxl);t.maxr = max(b.maxr, b.sum + a.maxr);t.maxs = max(max(a.maxs, b.maxs), a.maxr + b.maxl);return t;}
} seg;

我们可以通过线段树维护最大子段和来推广到其他类似的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/846902.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

研途无忧-beta冲刺

研途无忧-beta冲刺 一: alpha冲刺后项目还存在的问题及其探索思路和解决过程问题一:页面详情和加油站的数据同步问题 详细描述: 当前页面详情和加油站的数据同步功能尚未实现,包括点赞、收藏、评论和关注等功能。此外,发布帖子页面也尚未完善,需要进一步开发和优化。 探索…

75种K线基本形态

通过上一期的内容,我们已经了解了K线的绘制方法和关键因素,K线所包含的信息是极为丰富的,就以单根K线而言,一般上影线和阴线的实体表示股价的下压力量,下影线和阳线的实体则表示股价的上升力量。上影线和阴线实体比较长就说明股价下跌动量比较大,下影线和阳线实体较长则说…

我用了这款插件,工作效率大大提高啦~

备忘快贴 uTools 是一款呼之即来,即用即走的工具集软件。 备忘快贴是一款全新设计的备忘录 utools 插件,区别于手机自带的备忘录功能。传统的备忘录只是在需要时记录信息,而备忘快贴则不仅可以记录内容,还能轻松复制和粘贴,便于在多个场合使用。这款软件特别适合需要频繁编…

CDCL算法

1. CDCL伪代码 CDCL(CNF):副本 = CNF // 创建CNF的副本,不更改原CNFwhile true:while 副本含有单位子句:对副本使用单位传播;if 副本中含有取值为假的子句: // 发现冲突if 现在的决策层是0:return false; // 不能满足C = 子句学习(CNF, 副本) // 吸取教训根据C回到一个更早的决…

零基础快速入门软件测试

一、项目 1. 项目成员先简要了解一下软件项目组中所涉及的一些重要角色及关键词项目:软件研发项目,包括从前期项目预研、立项、组建项目团队、设计开发软件、测试调试、交付验收,以及软件运营等各项具体的工作 项目经理:软件项目的总负责人,既需要有广泛的计算机专业知识,…

全球气象数据ERA5的下载方法

本文介绍在ERA5气象数据的官方网站中,手动下载、Python代码自动批量下载逐小时、逐日与逐月的ERA5气象数据各类产品的快捷方法~本文介绍在ERA5气象数据的官方网站中,手动下载、Python代码自动批量下载逐小时、逐日与逐月的ERA5气象数据各类产品的快捷方法。ERA5(fifth gener…

高性能计算-NEON-图像旋转

1. 对512*512 png 四通道图像顺时针旋转90度 思路: 像素分块,对块内转置;再水平镜像。图像库使用 stb img 2. 代码 #include <stdio.h> #include <arm_neon.h>#include <stdlib.h> #define STB_IMAGE_IMPLEMENTATION #include "./stb/stb_image.h&quo…

使用自定义 MSBuild Task 阻止 git 的大文件提交

一个自定义 MSBuild Task 的实际案例NuGet Gallery | Jgrass.MSBuild.GitTask 前言 在 .NET 项目自定义 MSBuild Task 中提到,可以使用自定义 MSBuild Task 来实现自定义功能。 这里介绍实现的 git 提交大文件提交拦截功能。 引入 nuget 包之后,设置好要拦截的大小,内置的 L…

ElasticSearch学习笔记

ES7.x和ES8.x的学习笔记1.ElasticSearch概述 1.1 ElasticSearch是什么 Elaticsearch,简称为 ES,ES 是一个开源的高扩展的分布式全文搜索引擎,是整个Elastic Stack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上 百台服务器,处理PB级别的数…

不死的魔女与灾厄的少年

传闻......森林的深处里住着一位不死的魔女森林的深处,住着一位魔女。 她已经活了几十个世纪,每代王国的历史书籍中都有她的出现。 人们称她为: “不死的魔女” 寂静了百年的森林,在某一天,闯入了一个不速之客,他倒在了魔女的屋子前。 那是一个浑身染血的少年,不着片缕,…

地址冲突检测(DAD)

地址冲突检测(DAD) 目录地址冲突检测(DAD)一、前言二、免费ARP报文实验拓扑报文分析 一、前言 公网: public,互联网可以访问 ,地址必须唯一 私网:RFC1918隔离公网,安全复用 优点:地址段重叠使用 缺点:地址冲突 IPV6唯一本地地址 = IPV6私网地址,提供global id二、免…

2025年昆明理工大学MBA研究生招生人数

--昆工MBA考研、管理与经济学院、125100工商管理、125602项目管理、199管理类综合能力、F009 政治、F008政治+项目管理概论