## split函数 ```cpp #define IT set<node>::iterator IT split(int pos){ IT it = s.lower-bound(node(pos)); if (it->l == pos && it != s.end()) return it; --it; int v = it->v, l = it->l, r = it->r; s.erase(it); s.insert(node(l, pos - 1, v)); return s.insert(node(pos, r, v)).first; }
注意 set 自带的 lower-bound 和 upper-bound 的时间复杂度为\(\mathjaxcal{O}(log n)\)。 但使用 algorithm
库中的 lower-bound 和 upper-bound 函数对 set
中的元素进行查询,时间复杂度为 \(\mathjaxcal{O}(n)\)。似乎是 set
不支持随机访问的原因。
s.insert(node(pos, r, v)).first 返回的是插入元素的地址。
assign函数
1 2 3 4 5
voidassign(int l, int r, int v){ IT itr = split(r + 1), itl = split(l); s.erase(itl, itr); s.insert(node(l, r, v)); }
作用是推平一段区间,也是\(ODT\)时间复杂度的保证。
注意如果先 split 左端点再 split 右端点就会 RE,原因是 l 和 r 在一个 node
上时,split(r) 会 erase 这个 node 再重新插入,导致 split(l)
的迭代器失效。