颜色段均摊的线段树写法

机房用小肠写代码的大神 @GM_Joanna_ 发现线段树也能写 odt,我感觉确实。故记录下来。

前置知识:区间推平(颜色段均摊),ODT

区间推平:指的是对 进行某些查询,然后将 设置为相同值的操作。例子

下面假定你会了 ODT,然后我们下面用线段树实现相似的操作:找到每个被删除的颜色段,然后将他们的颜色设置为某个颜色。

考虑线段树当前节点为 ,如果全部是同一个颜色,那么返回,否则递归两个子树。由于线段树递归是先左再右的,所以可以顺序找到即将删除的区间。这个做法和 Segment Beats 是一样的复杂度分析,就是,每个颜色段提供 的势能,总共 个颜色段,所以复杂度为

具体找到一个被删除的区间的做法是,维护两个变量 ,表示当前最后一个颜色段是从 开始的,颜色为 。当线段树上找到一个颜色完全相同的区间时,如果该区间颜色和 一样就合并,否则

于是做完了。感觉上常数是很小的,实际上测试后发现差不多,甚至线段树有时候比较慢。下面是一些测试数据(单位:秒,程序 A 是 map 实现,程序 B 是线段树实现)。

这个测试在我的 github 仓库上有,感兴趣可以去看看,如果有更好的写法可以找我。代码我在洛谷剪贴板也放了一份。