【学习笔记】吉司机线段树

本文是一篇详细的学习线段树的笔记,特别介绍了吉司机线段树,即维护区间最值和历史最值的线段树。内容包括线段树结构体的定义、建树过程、懒标记的处理以及各种操作的实现,适合线段树初学者阅读。
摘要由CSDN通过智能技术生成

本文同步在洛谷博客上进行发表。

这是一篇刚开始学习线段树的小白都能看懂的良心学习笔记!

前置知识:含有懒标记的线段树(没别的了)。

总述

什么是吉司机线段树?

就是维护区间最值和区间历史最值的线段树,它的名字来源于吉如一老师,他在 2016 2016 2016 年发表了一篇集训队论文

不过为啥这位老师被称为吉司机我也不知道……

废话不多说,马上进入正题吧。

正题

例题:Luogu 6242

读完题我们发现,一般线段树题目只需要用到一个数组,而这道题用了两个,多出来了个 B B B 数组,是不是要拆成两棵树?

通过分析已知的所有关于 B B B 数组的条件,我们找出的答案是不用!

  1. B B B 数组最初和 A A A 数组完全相同
  2. 每次操作后,将 B B B 数组更新,使 B i = max ⁡ ( B i , A i ) B_i = \max(B_i,A_i) Bi=max(Bi,Ai)

这里我给出了两个条件,条件 1 1 1 B B B 数组的初始化,条件 2 2 2 B B B 数组的更新。显然可得: B i B_i Bi 是出现过的所有 A i A_i Ai 的最大值。

得出结论: B B B 数组维护 A A A 数组的历史最大值,两者公用一棵线段树

题干分析完之后,让我们来分析一下操作。

操作号 简述
1 1 1 区间加法
2 2 2 区间修改为最小值
3 3 3 区间求和
4 4 4 区间查询最大值
5 5 5 区间查询历史最大值中的最大值

接下来,我会分模块讲解(一定要往下看哟,有代码 /se)。

吉司机线段树本质上就是带懒标记的线段树,所以代码和线段树的前两个模板题也是大同小异的。

都有啥?

struct SegTree {
   };
void pushup()
void build()
void pushdown()
void modify()
// 此处省略N个modify……
int query()
// 此处省略N个query……

看着就码量惊人,所以我们要在保证代码可读性的基础上尝试减少码量,原因有二:

  1. 代码相对短,看着舒服(要不然会感觉像在写大 % 你)
  2. 由于这题代码不可避免的长(函数多,维护操作多),所以出错的概率也会比较高,错了之后调代码会令人崩溃。为了自己的心理健康着想,还是要把代码写的漂亮一点的。

具体怎样减少码量,我会在后文进行详细的描述。

线段树结构体
struct SegTree
{
   
	int sum, maxst, maxnd, maxhis, maxnum, l, r;
	int lazy1, lazy2, lazy3, lazy4;
	void clear() {
    lazy1 = lazy2 = lazy3 = lazy4 = 0; }
} tree[NR << 2];
  • s u m sum sum:区间内所有元素的和,在操作 3 3 3 时会用到。
  • m a x s t maxst maxst:区间内的最大值,在操作 2 2 2 和操作 4 4 4 时会用到。
  • m a x n d maxnd maxnd:区间内的严格次大值,在操作
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值