李超线段树学习笔记

本文深入探讨了李超树这一数据结构,解释了其在二维坐标系中处理斜率线段区间查询与修改的问题。通过定义优势线段并详细描述了线段树的更新与查询过程,证明了算法的正确性。文章指出,李超树的空间复杂度为O(n),插入操作的时间复杂度在最坏情况下为O(nlog^2n),但如果是直线则为O(nlogn),查询通常为O(nlogn)。虽然未提供例题,但全文提供了清晰的学习笔记和理解路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
其实我很早就听说过李超树了,之前也有好多次想学这个东西,但是都因为各种原因没有学习。现在终于抽出了点时间学习了这个数据结构。

进入正题。

首先是李超树能解决什么问题。可以理解为,现在有一个二维坐标系,横坐标是正整数。李超树可以解决给一个区间加入一条斜率不一定是0的线段,询问一个所有覆盖这个横坐标的线段的最大或最小值。或者在一个横坐标区间中的所有线段的最大或最小值(可能只有部分在区间内)。

下面介绍一下怎么维护。这里顺带了一个正确性证明。我看网上似乎很少有人证明李超树的正确性。我自己想了一下,觉得不是很好描述证明,但是我们只要把所有可能成为答案的情况都维护出来并且在查询答案时将这些情况都考虑到,那么我们就可以算是有了正确性保证了。

那么下面说一下算法流程。

我们对于每一个区间,维护一条优势线段。我想了想,感觉网上有些定义好像不太严谨。网上很多时候优势线段的定义是,这条线段能覆盖这个横坐标区间,并且在这个区间暴露长度最大的线段。以最大值为例,就是在区间里最大值在这条线段取到的位置最多的线段。但是实际在写的时候,它线段树上的父亲节点的那条线段可能在这个区间取到最大值的时候比它还多,只是那条直线的信息没有下传。所以我觉得定义应该是所有已经下传到这个区间的线段中是在该线段上取到纵坐标最大值最多的一条线段。

下面我们都以求最大的纵坐标为例讲解。

有了这个定义之后,我们每次查询经过一个横坐标的所有线段对应的纵坐标最大值时,我们从线段树的根一直顺着那一条链遍历到对应叶子,把每个区间的优势线段在这个横坐标的取到的纵坐标取max就是答案。

那么我们考虑在加入一条线段时如何更新。首先,我们像常规的区间修改一样,把这条线段拆分成被它覆盖的 l o g log log个区间。然后对于每个区间,我们判断它是否能成为新的优势线段,判断方法是如果在区间左右端点取值都比原来线段大,那么就直接成为新的优势线段,而被完全覆盖的原线段在更小的区间里也不可能成为优势线段了,所以直接返回。如果比优势线段的左端点或者右端点中的一个大,那么如果它在区间中点处比原优势线段值大,那么它可以成为新的优势线段。但是原优势线段在自己那一段更大的那一半区间仍可能成为优势线段,于是将原优势线段信息下传更新。如果当前下传的线段比当前区间优势线段的左右端点的一个值大,并且在中点处没有原优势线段值大,那么它在这个区间不能成为优势线段,但是在自己端点取值更大的那一半区间仍可能成为最大值。于是更新过程就描述完了。

下面我们考虑这个算法的复杂度。空间复杂度显然是 O ( n ) O(n) O(n)的。时间复杂度是 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)的。对于修改,我们首先定位到 l o g log log个子区间,然后在每个子区间都可能递归到一个叶子,于是复杂度是两个 l o g log log的。但是不难发现,由于不可能每个子区间都是根,所以第二个 l o g log log的常数比较小。特别地,如果插入的是直线,那么我们不用递归到 l o g log log个子区间,那么修改复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)的。对于查询,我们复杂度通常是 O ( n l o g n ) O(nlogn) O(nlogn)的。我们只需要递归到对应叶子,或者像常规线段树区间查询一样找到被它覆盖的 l o g log log个区间,就可以得到答案。

例题可以找我其他博客,本篇作为学习笔记就先不放例题了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值