diff --git a/trees/odt.cc b/trees/odt.cc new file mode 100644 index 0000000..afcffd5 --- /dev/null +++ b/trees/odt.cc @@ -0,0 +1,49 @@ +template +struct ODT { + struct Info { + IndexType l, r; + mutable T val; + Info(const IndexType& l, const IndexType& r, const T& val) : l(l), r(r), val(val) {} + friend inline bool operator<(const Info& lhs, const Info& rhs) { return lhs.l < rhs.l; } + }; + + set info; + + ODT() = delete; + ODT(const IndexType& left, const IndexType& right, const T& val) : info {{ left, right, val }} {} + + typename set::iterator split(const IndexType& x) { + auto it = info.lower_bound({ x, {}, {} }); + if (it != info.end() and it->l == x) { + return it; + } + --it; + auto [l, r, val] = *it; + info.erase(it); + info.emplace(l, x - 1, val); + return info.emplace(x, r, val).first; + } + + void assign(const IndexType& l, const IndexType& r, const T& val) { + auto ri = split(r + 1), li = split(l); + info.erase(li, ri); + info.emplace(l, r, val); + } + + void transform(const IndexType& l, const IndexType& r, const function& operation) { + auto ri = split(r + 1), li = split(l); + for (; li != ri; ++li) { + li->val = operation(*li); + } + } + + template + U accumulate(const IndexType& l, const IndexType& r, U&& init, const function& operation = std::plus()) { + auto ri = split(r + 1), li = split(l); + U res = init; + for (; li != ri; ++li) { + res = operation(res, *li); + } + return res; + } +};