珂朵莉树算法

具体实现

感觉用 std::map 更加好写. 因为储存的区间都是连续的,假设两个相邻指针的左端点是 l1<l2l_1\lt l_2,那么我们就知道第一个区间实际上是 [l1,l21][l_1, l_2-1].

Chtholly Tree with std::map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class ChthollyTree {
std::map<int, /* data to maintain */> mp;

public:
void split(int l) {
// 找出 l 所在的区间
auto it = std::prev(mp.upper_bound(l));
// 先复制一遍数据
mp[l] = it->second;
}

// assign [l, r] to /* data */
void assign(int l, int r, /* data */) {
split(l), split(r + 1);
auto it = mp.find(l);
while (it->first != r + 1)
it = mp.erase(it);
mp[l] = /* data */;
}

// Compute the result for [l, r]
void perform(int l, int r) {
split(l), split(r+1);
auto it = mp.find(l);
while(it->first != r+1) {
// Do computation ...
it = std::next(it);
}
}
};

算法时间复杂度分析

为什么一定要学习如何分析珂朵莉树的时间复杂度?

珂朵莉树时间复杂度的正确性基于针对操作的分析,分析时间复杂度通常需要分析“连续段”数量的变化,才能计算操作的均摊时间复杂度。因此学会分析时间复杂度是正确使用珂朵莉树的关键所在。(否则只能期待玄学出现或者祈祷出题人不会卡了


珂朵莉树的推广


例题

其实也不算例题,毕竟没有哪一道题的标答是奔着珂朵莉树去的,只能说可以用珂朵莉树的思想去做题