珂朵莉树学习笔记
0x00 什么是珂朵莉树#
所谓珂朵莉树,就是颜色段均摊。它并不是树形数据结构,而是线性数据结构。
珂朵莉树的本质是合并一些有着相同信息的区间,以达到节省时间的效果。这里的信息一般是颜色,但也有例外。
珂朵莉树的修改与询问都是暴力,这使得珂朵莉树几乎无法处理区间赋值之外的区间修改或查询,但是也让珂朵莉树有非常广泛的用途。
0x01 常见的珂朵莉树写法#
珂朵莉树通常将区间转化为值,并使用 std::set
来维护每个区间,同一个区间里的值是相同的。代码如下:
struct node {
int l, r; mutable int v;
node(int L, int R = -1, int V = 0): l(L), r(R), v(V) {}
bool operator < (const node& o) const { return l < o.l; }
};
typedef set<node>::iterator IT;
set<node> s;
代码中的 node
是维护了一个
珂朵莉树有两个基本操作:
- split 裂块
IT split(int pos) {
IT it = s.lower_bound(node(pos));
if (it != s.end() && it->l == pos) return it;
int L = (-- it)->l, R = it->r, V = it->v;
s.erase(it), s.insert(node(L, pos - 1, V));
return s.insert(node(pos, R, V)).first;
}
-
split
的作用是将 所在的块 分裂为 两块,时间复杂度 , 是当前std::set
内区间的个数。 -
assign 区间赋值
void assign(int l, int r, int val = 0) {
IT itr = split(r + 1), itl = split(l);
s.erase(itl, itr);
s.insert(node(l, r, val));
}
- 随着
split
,珂朵莉树中的区间个数会越来越多,导致复杂度爆炸,我们需要区间赋值操作来减少区间个数。区间赋值将 中的区间删除,重新合并为一段,时间复杂度 , 是删除的区间个数。
来模拟一下?
设原先区间是 assign
操作先是通过 split
将区间变成 erase
,删除了
初始化只需插入
0x02 珂朵莉树的复杂度与应用#
珂朵莉树复杂度是基于均摊的:
- 初始插入
个区间, 次assign
每次最多增加两个区间(两端的split
),总共最多出现 个区间。 - 每个区间只会被删除一次,故所有
split
与assign
操作的总复杂度为 ,均摊每次 。 - 同时,如果珂朵莉树的区间询问与区间赋值绑定,则区间询问的时间复杂度也是
,均摊 。
基于均摊,珂朵莉树可以以非常优秀的复杂度完成暴力才能维护的操作,这使得它有非常多的应用。例题:
LOJ #6284. 数列分块入门 8
区间询问等于一个数
的元素,并将这个区间的所有元素改为 。
区间询问与区间修改绑定,可以使用珂朵莉树暴力处理询问。时间复杂度
洛谷 T314507 猫猫的烟花易冷 2
区间赋值,区间查第
小数。
这题询问可与修改不绑定,好像与珂朵莉树没有任何关系!
先思考只有单点修改怎么做,这显然是 P2617 Dynamic Rankings。考虑这题的分块做法,维护每种颜色的块前缀和。观察一下,发现不仅支持单点修改,还支持区间同一颜色的修改。那么用珂朵莉树维护相同颜色的区间,assign
时对每个删除的区间修改前缀和即可。散块的话需要再用一个支持区间修改单点查询的分块维护。时间复杂度
类似地,用 P3332 [ZJOI2013] K大数查询 的树套树代替分块可以做到
在随机数据下,珂朵莉树内的区间个数是
CF896C Willem, Chtholly and Seniorious
区间加、区间赋值、区间查询
小值、区间查询 次方和。数据随机。
直接跑暴力就做完了。
0x03 珂朵莉树的拓展#
维护的信息大多数情况是颜色,但也可以不是颜色。这类题和前面的珂朵莉树比较像的,也有搭配根号重构完全不像的。还是看例题吧:
[QwQOI2020] III
区间从小到大或从大到小排序,单点查询
用珂朵莉树维护每个排好序的区间(从小到大、从大到小),那么每次排序即推平。
每个区间维护一棵线段树,用线段树分裂、合并维护就行了。
时间复杂度
洛谷 P3391 【模板】文艺平衡树
次区间翻转,最后输出整个序列。
区间翻转,维护区间的话可以做到一次
设立一个阈值
翻转一次
例题 2 重构的思想还可以继续拓展,可以看很厉害的这篇:ODT的映射思想的推广。不过这篇后面讲的带插区间众数用珂朵莉树好像没有什么必要。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下