【模板】线段树合并
这是线段树的最后一个知识点啦,终于不用继续练码量超大的线段树了,因为笔者已经掌握了~
例题:n只奶牛构成了一个树形的公司,每个奶牛有一个能力值pi,1号奶牛为树根。
问对于每个奶牛来说,它的子树中有几个能力值比它大的。
solution:
做法是每个点开一棵线段树,插入这个结点上的数,根节点就为这个点的序号。如果能把一个结点的线段树的信息在合理的时间内全部插入(或者说「合并」)到它父亲的线段树中,就可以由下往上做一遍树上递推,这样每个结点的线段树都存储的是整棵子树的信息了。
先放代码吧:
这个代码还是相当好理解的,无需赘述。下面来证明一下复杂度。(我想了一中午终于想出一个超简洁的证明 —— 本来以为会很复杂的)
从代码中可以看出合并两棵树的复杂度约等于这两棵树 重合 的结点数。假如初始所有的线段树点数总和为 N N N 。因为只要合并两个节点,节点总个数就会少掉一个,所以复杂度应该是 O ( N ) O ( N ) O(N) 的。
所以不是所有情况下的线段树合并都是 O ( n l o g n ) O ( n log n ) O(nlogn) 的。
一般情况下我们只会对每个节点开动态开一条链,所以 N = n l o g n N = n log n N=nlogn ,复杂度才会是 O ( n l o g n ) O ( n log n ) O(nlogn) 。
哇怎么这么短就写完了 ……
update:「abc183F」Confluence
题意:n个人,每个人属于一个班级ci,这些人会有些小团体(并查集)
两种操作:
1 a b,将a所在的集体和b所在的集体合并
2 x y,问在x的集体中有多少人在y班
第一种做法启发式合并,每次将点数较少的接到点数较多的上面。具体可以用 m a p map map之类的 S T L STL STL来存集合。
第二种方法是线段树合并。我们把一个点所含的种类 [ 1 , 2 e 5 ] [1,2e5] [1,2e5] 看成一个树的结构,时间复杂度是严格 O ( n l o g n ) O(nlogn) O(nlogn) 的。
这个想法很妙。我们把一个线性的单点合并放到动态开点线段树上,这样每次合并一个点都删除了一个点,保证了算法的高效。
第二种算法的时间复杂度显然是优于第一种的,第一种做法只能“单个搬运”,导致合并代价是不稳定的。而第二种则把若干子树进行“整体搬运”,我们也通过理论证明了它时间上界和优秀的搬运性质(我们发现它在整个合并过程中没有新建点)。
__EOF__

本文链接:https://www.cnblogs.com/cqbzly/p/17530374.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2021-07-28 【题解】CF1550E Stringforces
2021-07-28 【题解】CF1550F Jumping Around