珂朵莉树/颜色段均摊

珂朵莉树

2024 12月 02 周一
858 字 · 4 分钟

看到幸福的随机数据题就该用幸福的珂朵莉树啦

0.基本定义

我也不知道 lxl dalao 怎么想出来这种 神仙 的算法的。反正就是在 CF896C 这道题里,数据随机,并且有区间赋值,就可以做了。

其实本质上就是一个 set 维护的一段段的颜色,每种操作都是 暴力处理 的。

1.代码

定义

struct Chtholly
{
int l,r;
mutable int val;
bool operator<(const Chtholly &a) const {return l < a.l;};
Chtholly(int l,int r = 0,int val = 0):l(l),r(r),val(val){};
};
set<Chtholly> odt;
#define iter set<Chtholly>::iterator

这就是珂朵莉树的定义,维护的是一个段,表示区间 [l,r][l,r] 内都是 val,注意 val 前面那个 mutable,很重要。

因为在用迭代器迭代 set 的时候,迭代器的原型是 std::set<Chtholly>::const_iterator,不加 mutable 不支持修改,所以必须带一个 mutable 才能用迭代器修改。

还有用 map 和手搓链表实现的,但我觉得没什么用,复杂度还不如用 set。

分裂

iter split(int pos)
{
iter it = odt.lower_bound(Chtholly(pos));
if(it != odt.end() && it->l == pos)
return it;
--it;
if(it->r < pos)
return odt.end();
int l = it->l,r = it->r,val = it->val;
odt.erase(it);
odt.insert(Chtholly(l,pos - 1,val));
return odt.insert(Chtholly(pos,r,val)).first;
}

本质就是找到第一个左端点大于等于 pos 的段,删除这一段后插入两个分裂后的段,分裂为 [l,pos−1],[pos,r][l,pos - 1],[pos,r]

一眼可以看出,分裂肯定会导致段数暴增,进而导致复杂度起飞,所以下面的区间推平就是为防止这种情况出现。

区间赋值/区间推平

void assign(int l,int r,int x)
{
iter rit = split(r + 1),lit = split(l);
odt.erase(lit,rit);
odt.insert(Chtholly(l,r,x));
}

如上,就是分裂出区间后暴力删除并插入。

注意,要先分裂 r+1r + 1 再分裂 ll,因为反过来会导致迭代器失效,造成各种奇奇怪怪的 WA&RE。

区间操作

Any perform(int l,int r,...)
{
iter rit = split(r + 1),lit = split(l);
// Perform Here
}

2.复杂度

这种东西一看就是暴力数据结构,但是神奇的是,在保证数据随机并且有区间推平的情况下,复杂度为 O(nlog⁡log⁡n)\Omicron(n \log \log n),并且常数很优秀。

具体证明看 CF 上 ODT 的证明,大致意思是段数是 O(log⁡n)\Omicron(\log n) 级别的,然后对颜色段的操作复杂度是 O(log⁡n)\Omicron(\log n) 的,所以总复杂度是 O(nlog⁡log⁡n)\Omicron(n \log \log n) 的。

总结就是,用 set 实现的是 O(nlog⁡log⁡n)\Omicron(n \log \log n),map 和链表都是 O(nlog⁡n)\Omicron(n \log n)。

3.扩展 ODT

由上得,ODT 是靠区间推平来维护复杂度的,可是有的出题人,会构造的全是查询的数据来卡掉 ODT。

这个时候,就该用上扩展 ODT 了。

知周所众,替罪羊树有不用旋转还能平衡的秘诀就是,只要不平衡,就炸了重构…

所以就可以结合一下 ODT 和替罪羊树,就有了保证根号复杂度的 ODT,并且 无需区间推平。

比如这道↗

发现,刚开始的序列是一个公差为 +1+1 的等差数列,并且每次操作均是置换群上的置换,所以我们完全可以维护置换与对原序列的映射。

然后,只要段数大于 B(=n)B( = \sqrt{n}) 时,就算一下当前序列,然后重新构造扩展 ODT。

还有一种用法:结点对区间的映射,但是模板都是黑题,不会。


Thanks for reading!

珂朵莉树/颜色段均摊

2024 12月 02 周一
858 字 · 4 分钟