From 7e9f23f8e73d62ed54fc5c12f04aaf375a993af3 Mon Sep 17 00:00:00 2001 From: subcrip Date: Wed, 4 Sep 2024 16:51:50 +0800 Subject: [PATCH] Add trees/segtree_beats.cc Signed-off-by: subcrip --- trees/segtree_beats.cc | 139 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 trees/segtree_beats.cc diff --git a/trees/segtree_beats.cc b/trees/segtree_beats.cc new file mode 100644 index 0000000..07ae590 --- /dev/null +++ b/trees/segtree_beats.cc @@ -0,0 +1,139 @@ +template> class segtree { +private: + using size_type = uint64_t; + using info_type = Addable_Info_t; + using tag_type = Tag_t; + size_type _max; + vector d; + vector b; + void pull(size_type p) { + d[p] = d[p * 2] + d[p * 2 + 1]; + } + void push(size_type p, size_type left_len, size_type right_len) { + if (b[p].val == INF) return; + pushtag(p * 2, left_len, b[p]); + pushtag(p * 2 + 1, right_len, b[p]); + b[p] = tag_type(); + } + void pushtag(size_type p, size_type len, const tag_type& c) { + if (d[p].mx <= c.val) return; + d[p].val += (c.val - d[p].mx) * d[p].cnt; + d[p].mx = c.val; + b[p] = c; + } + void set(size_type s, size_type t, size_type p, size_type x, const info_type& c) { + if (s == t) { + d[p] = c; + return; + } + size_type m = s + (t - s >> 1); + if (s != t) push(p, m - s + 1, t - m); + if (x <= m) set(s, m, p * 2, x, c); + else set(m + 1, t, p * 2 + 1, x, c); + pull(p); + } + + void range_apply(size_type s, size_type t, size_type p, size_type l, size_type r, const tag_type& c) { + if (d[p].mx <= c.val) return; + if (l <= s && t <= r && d[p].se < c.val) { + pushtag(p, t - s + 1, c); + return; + } + size_type m = s + (t - s >> 1); + push(p, m - s + 1, t - m); + if (l <= m) range_apply(s, m, p * 2, l, r, c); + if (r > m) range_apply(m + 1, t, p * 2 + 1, l, r, c); + pull(p); + } + info_type range_query(size_type s, size_type t, size_type p, size_type l, size_type r) { + if (l <= s && t <= r) { + return d[p]; + } + size_type m = s + (t - s >> 1); + info_type res = {}; + push(p, m - s + 1, t - m); + if (l <= m) res = res + range_query(s, m, p * 2, l, r); + if (r > m) res = res + range_query(m + 1, t, p * 2 + 1, l, r); + return res; + } + void build(const Sequence& a, size_type s, size_type t, size_type p) { + if (s == t) { + d[p] = a[s]; + return; + } + int m = s + (t - s >> 1); + build(a, s, m, p * 2); + build(a, m + 1, t, p * 2 + 1); + pull(p); + } +public: + segtree(size_type __max) : d(4 * __max), b(4 * __max), _max(__max - 1) {} + segtree(const Sequence& a) : segtree(a.size()) { + build(a, {}, _max, 1); + } + void set(size_type i, const info_type& c) { + set({}, _max, 1, i, c); + } + + void range_apply(size_type l, size_type r, const tag_type& c) { + range_apply({}, _max, 1, l, r, c); + } + void apply(size_type i, const tag_type& c) { + range_apply(i, i, c); + } + info_type range_query(size_type l, size_type r) { + return range_query({}, _max, 1, l, r); + } + info_type query(size_type i) { + return range_query(i, i); + } + Sequence serialize() { + Sequence res = {}; + for (size_type i = 0; i <= _max; ++i) { + res.push_back(query(i)); + } + return res; + } + const vector& get_d() { + return d; + } +}; +struct Tag { + ll val = INF; +}; +struct Info { + ll val = 0, mx = 0, se = 0, cnt = 0; +}; +Info operator+(const Info &a, const Info &b) { + if (a.mx == b.mx) { + return { + .val = a.val + b.val, + .mx = a.mx, + .se = max(a.se, b.se), + .cnt = a.cnt + b.cnt, + }; + } else if (a.mx > b.mx) { + return { + .val = a.val + b.val, + .mx = a.mx, + .se = max(a.se, b.mx), + .cnt = a.cnt, + }; + } else { + return { + .val = a.val + b.val, + .mx = b.mx, + .se = max(a.mx, b.se), + .cnt = b.cnt, + }; + } +} + + +// Default leaves: +// Info { +// .val = INFLL, +// .mx = INFLL, +// .se = 0, +// .cnt = 1, +// } \ No newline at end of file