diff --git a/segmenttree/point-update-range-get_nonrecursive.hpp b/segmenttree/point-update-range-get_nonrecursive.hpp index a4572acc..a38d32d6 100644 --- a/segmenttree/point-update-range-get_nonrecursive.hpp +++ b/segmenttree/point-update-range-get_nonrecursive.hpp @@ -119,19 +119,6 @@ template struct RangeMinimumQuery : public NonrecursiveSegmentTree< }; }; -// Range Maximum Query -// - get: return max(x_l, ..., x_{r - 1}) -template struct RangeMaximumQuery : public NonrecursiveSegmentTree { - using SegTree = NonrecursiveSegmentTree; - T merge_data(const T &vl, const T &vr) override { return std::max(vl, vr); }; - T data2ret(const T &v, const bool &q) override { return v; } - T merge_ret(const T &vl, const T &vr) override { return std::max(vl, vr); }; - RangeMaximumQuery(const std::vector &seq, T defaultmax) - : SegTree::NonrecursiveSegmentTree() { - SegTree::initialize(seq, defaultmax); - }; -}; - template struct PointUpdateRangeSum : public NonrecursiveSegmentTree { using SegTree = NonrecursiveSegmentTree; T merge_data(const T &vl, const T &vr) override { return vl + vr; }; diff --git a/segmenttree/range-update-range-get.hpp b/segmenttree/range-update-range-get.hpp deleted file mode 100644 index 43a0ba62..00000000 --- a/segmenttree/range-update-range-get.hpp +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once -#include -#include -#include -#include - -// CUT begin -template struct LazySegmentTree { - TLAZY zero_lazy; - TRET zero_ret; - int N; - int head; - std::vector data; - std::vector lazy; - - // Here, you have to calculate data[pos] from children (data[l], data[r]), - // Assumptions: `lazy[pos] = lazy[l] = lazy[r] = zero_lazy` - virtual void merge_data(int pos) = 0; - - // Here, you must propagate lazy[pos] and update data[pos] by reflecting lazy[pos], without - // inconsistency After this, lazy[pos] must be zero_lazy. - virtual void reflect_lazy(int pos) = 0; - - // operate d to lazy[pos] (merge two TLAZY's) - virtual void overlap_lazy(int pos, const TLAZY &d) = 0; - - // Assumption: `lazy[pos] = zero_lazy` - virtual TRET data2ret(int pos, const TQUERY &query) = 0; - - virtual TRET merge_ret(const TRET &l, const TRET &r, const TQUERY &query) = 0; - - ////// general description ////// - LazySegmentTree() = default; - void initialize(const std::vector &data_init, const TDATA &zero_data, - const TLAZY &zero_lazy_, const TRET &zero_ret_) { - N = data_init.size(); - head = 1; - while (head < N) head <<= 1; - zero_lazy = zero_lazy_; - zero_ret = zero_ret_; - data.assign(head * 2, zero_data); - lazy.assign(head * 2, zero_lazy); - std::copy(data_init.begin(), data_init.end(), data.begin() + head); - for (int pos = head; --pos;) merge_data(pos); - } - - void _update(int begin, int end, const TLAZY &delay, int pos, int l, int r) { - // Operate `delay` to the node pos - // After this, lazy[pos] MUST be zero so that merge_data() works correctly - if (begin <= l and r <= end) { // Update whole [l, r) by delay - overlap_lazy(pos, delay); - reflect_lazy(pos); - } else if (begin < r and l < end) { // Update somewhere in [l, r) - reflect_lazy(pos); - _update(begin, end, delay, pos * 2, l, (l + r) / 2); - _update(begin, end, delay, pos * 2 + 1, (l + r) / 2, r); - merge_data(pos); - } else - reflect_lazy(pos); - } - - void update(int begin, int end, const TLAZY &delay) { _update(begin, end, delay, 1, 0, head); } - - TRET _get(int begin, int end, int pos, int l, int r, - const TQUERY &query) // Get value in [begin, end) - { - reflect_lazy(pos); - if (begin <= l and r <= end) - return data2ret(pos, query); - else if (begin < r and l < end) { - TRET vl = _get(begin, end, pos * 2, l, (l + r) / 2, query); - TRET vr = _get(begin, end, pos * 2 + 1, (l + r) / 2, r, query); - return merge_ret(vl, vr, query); - } else - return zero_ret; - } - TRET get(int begin, int end, const TQUERY &query = NULL) { - return _get(begin, end, 1, 0, head, query); - } -}; - -// Range Update & Range Sum -// - get(l, r): return x_l + ... + x_{r - 1} -// - update(l, r, val): x_l, ..., x_{r - 1} <- val -template -struct RangeUpdateRangeSum - : public LazySegmentTree, std::pair, T, std::tuple<>> { - using TDATA = std::pair; - using TLAZY = std::pair; - using SegTree = LazySegmentTree>; - using SegTree::data; - using SegTree::lazy; - void merge_data(int i) override { - data[i] = std::make_pair(data[i * 2].first + data[i * 2 + 1].first, - data[i * 2].second + data[i * 2 + 1].second); - }; - void reflect_lazy(int i) override { - if (lazy[i].second) { - if (i < SegTree::head) overlap_lazy(i * 2, lazy[i]), overlap_lazy(i * 2 + 1, lazy[i]); - data[i].first = lazy[i].first * data[i].second; - } - lazy[i].second = false; - } - void overlap_lazy(int i, const TLAZY &p) override { - if (p.second) lazy[i] = p; - } - T data2ret(int i, const std::tuple<> &) override { return data[i].first; } - T merge_ret(const T &l, const T &r, const std::tuple<> &) override { return l + r; } - void update(int l, int r, T val) { SegTree::update(l, r, TLAZY(val, true)); } - T get(int l, int r) { return SegTree::get(l, r, {}); } - RangeUpdateRangeSum(const std::vector &seq) : SegTree::LazySegmentTree() { - std::vector vec; - for (const auto &x : seq) vec.emplace_back(x, 1); - SegTree::initialize(vec, TDATA(0, 0), TLAZY(0, false), 0); - } -}; diff --git a/segmenttree/segment_tree_2d.hpp b/segmenttree/segment_tree_2d.hpp deleted file mode 100644 index d9d97d4b..00000000 --- a/segmenttree/segment_tree_2d.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once -#include -#include - -// CUT begin -// 2D Segment Tree (point-update, range-get) -// - 0-indexed -// - Conditions for operations: -// - merge_data: [TDATA, TDATA] -> TDATA, e(defaultDATA, x) == x, e(x, y) == e(y, x) -// - data2ret: [TDATA, TQUERY] -> TRET, f(defaultDATA, q) == defaultRET -// - merge_ret: [TRET, TRET] -> TRET, g(defaultRET, x) == x, g(x, y) = g(y, x) -// - commutability f(e(x, y), q) == g(f(x, q), f(y, q)) -template -struct SegmentTree2D { - int H, W; - int hhead, whead; - TDATA defaultDATA; - TRET defaultRET; - E merge_data; - F data2ret; - G merge_ret; - int DH, DW; - std::vector data; - inline TDATA &at(int h, int w) { return data[DW * h + w]; } - - inline void _merge_w(int h, int w) { - if (2 * w + 2 < DW) - at(h, w) = merge_data(at(h, 2 * w + 1), at(h, 2 * w + 2)); - else if (2 * w + 2 == DW) - at(h, w) = at(h, 2 * w + 1); - else - at(h, w) = defaultDATA; - } - inline void _merge_h(int h, int w) { - if (2 * h + 2 < DH) - at(h, w) = merge_data(at(2 * h + 1, w), at(2 * h + 2, w)); - else if (2 * h + 2 == DH) - at(h, w) = at(2 * h + 1, w); - else - at(h, w) = defaultDATA; - } - SegmentTree2D(const std::vector> &mat, TDATA defaultDATA, E merge_data, - F data2ret, G merge_ret) - : H(mat.size()), W(mat[0].size()), defaultDATA(defaultDATA), - defaultRET(data2ret(defaultDATA, TQUERY(0))), merge_data(merge_data), data2ret(data2ret), - merge_ret(merge_ret) { - int Htmp = 1, Wtmp = 1; - while (Htmp < H) Htmp <<= 1; - while (Wtmp < W) Wtmp <<= 1; - hhead = Htmp - 1, whead = Wtmp - 1; - DH = hhead + H, DW = whead + W; - data.assign(DH * DW, defaultDATA); - for (int h = 0; h < H; h++) - for (int w = 0; w < W; w++) { at(hhead + h, whead + w) = mat[h][w]; } - for (int h = DH - 1; h >= hhead; h--) { - for (int w = whead - 1; w >= 0; w--) _merge_w(h, w); - } - for (int h = hhead - 1; h >= 0; h--) { - for (int w = 0; w < DW; w++) _merge_h(h, w); - } - } - void update(int h, int w, TDATA x) { - h += hhead, w += whead; - at(h, w) = x; - for (int pos = h; pos;) { - pos = (pos - 1) / 2; - _merge_h(pos, w); - } - for (int iw = w; iw;) { - iw = (iw - 1) / 2; - for (int ih = h;;) { - _merge_w(ih, iw); - if (!ih) break; - ih = (ih - 1) / 2; - } - } - } - TRET _get_h(int hl, int hr, int wl, int wr, int lo, int hi, int id_, TQUERY q) { - if (hr <= lo or hi <= hl) return defaultRET; - if (hl <= lo and hi <= hr) return _get_w(wl, wr, 0, whead + 1, id_, 0, q); - return merge_ret(_get_h(hl, hr, wl, wr, lo, (lo + hi) / 2, 2 * id_ + 1, q), - _get_h(hl, hr, wl, wr, (lo + hi) / 2, hi, 2 * id_ + 2, q)); - } - TRET _get_w(int wl, int wr, int lo, int hi, int id_h, int id_w, TQUERY q) { - if (wr <= lo or hi <= wl) return defaultRET; - if (wl <= lo and hi <= wr) return data2ret(at(id_h, id_w), q); - return merge_ret(_get_w(wl, wr, lo, (lo + hi) / 2, id_h, 2 * id_w + 1, q), - _get_w(wl, wr, (lo + hi) / 2, hi, id_h, 2 * id_w + 2, q)); - } - // [hl, hr) * [wl, wr) - TRET get(int hl, int hr, int wl, int wr, TQUERY q) { - return _get_h(hl, hr, wl, wr, 0, hhead + 1, 0, q); - } - friend std::ostream &operator<<(std::ostream &os, SegmentTree2D s) { - os << "[SegmentTree" << s.H << "*" << s.W << "\n"; - for (int h = 0; h < s.H; h++) { - os << "["; - for (int w = 0; w < s.W; w++) os << s.at(h + s.hhead, w + s.whead) << ","; - os << "]\n"; - } - return os << "]"; - } -}; diff --git a/segmenttree/test/range-affine-range-sum.test.cpp b/segmenttree/test/range-affine-range-sum.test.cpp deleted file mode 100644 index b4493da5..00000000 --- a/segmenttree/test/range-affine-range-sum.test.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "../../modint.hpp" -#include "../range-update-range-get.hpp" -#include -#define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum" - -// RangeAffineRangeSum -// - update: x_i -> a * x_i + b for i in [l, r) -// - get: return x_l + ... + x_{r - 1} -template -struct RangeAffineRangeSum : public LazySegmentTree, std::pair, T, bool> { - using TDATA = std::pair; - using TLAZY = std::pair; - using SegTree = LazySegmentTree; - void merge_data(int pos) { - this->data[pos].first = this->data[pos * 2].first + this->data[pos * 2 + 1].first; - this->data[pos].second = this->data[pos * 2].second + this->data[pos * 2 + 1].second; - } - void reflect_lazy(int pos) { - if (pos < this->head) { - overlap_lazy(pos * 2, this->lazy[pos]); - overlap_lazy(pos * 2 + 1, this->lazy[pos]); - } - this->data[pos].first = this->lazy[pos].first * this->data[pos].first + - this->lazy[pos].second * this->data[pos].second; - this->lazy[pos] = this->zero_lazy; - } - void overlap_lazy(int pos, const TLAZY &d) { - this->lazy[pos] = std::make_pair( - this->lazy[pos].first * d.first, this->lazy[pos].second * d.first + d.second); - } - T data2ret(int pos, const bool &) { return this->data[pos].first; } - T merge_ret(const T &l, const T &r, const bool &) { return l + r; } - RangeAffineRangeSum(const std::vector &seq) : SegTree::LazySegmentTree() { - std::vector> vinit; - for (auto x : seq) vinit.emplace_back(x, 1); - SegTree::initialize(vinit, std::make_pair(0, 0), std::make_pair(1, 0), T(0)); - }; -}; - -using mint = ModInt<998244353>; - -int main() { - std::cin.tie(nullptr), std::ios::sync_with_stdio(false); - - int N, Q; - std::cin >> N >> Q; - - std::vector A(N); - for (auto &a : A) std::cin >> a; - RangeAffineRangeSum segtree(A); - while (Q--) { - int q, l, r; - std::cin >> q >> l >> r; - if (q) { - std::cout << segtree.get(l, r) << '\n'; - } else { - mint b, c; - std::cin >> b >> c; - segtree.update(l, r, std::make_pair(b, c)); - } - } -} diff --git a/segmenttree/test/segment_tree_2d.test.cpp b/segmenttree/test/segment_tree_2d.test.cpp deleted file mode 100644 index 1ff7efe6..00000000 --- a/segmenttree/test/segment_tree_2d.test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "../segment_tree_2d.hpp" -#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1068" - -#include -using namespace std; - -int main() { - auto f = [](int l, int r) { return min(l, r); }; - auto g = [](int x, int q) { return x; }; - while (true) { - int H, W, Q; - cin >> H >> W >> Q; - vector> mat(H, vector(W)); - if (!H) break; - for (auto &vec : mat) - for (auto &x : vec) cin >> x; - int INF = (1LL << 31) - 1; - SegmentTree2D rmq(mat, INF, f, g, f); - while (Q--) { - int xl, yl, xr, yr; - cin >> xl >> yl >> xr >> yr; - printf("%d\n", rmq.get(xl, xr + 1, yl, yr + 1, -1)); - } - } -} diff --git a/segmenttree/test/segment_tree_2d_pointadd.test.cpp b/segmenttree/test/segment_tree_2d_pointadd.test.cpp deleted file mode 100644 index 9c2cc9a9..00000000 --- a/segmenttree/test/segment_tree_2d_pointadd.test.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2842" -#include "../segment_tree_2d.hpp" - -#include -#include -#include -#include -#include -#include -using namespace std; - -int main() { - int H, W, T, Q; - cin >> H >> W >> T >> Q; - - // Point add, range sum (like binary-indexed-tree) - vector> mat(H, vector(W)); - auto f = [](int l, int r) { return l + r; }; - auto g = [](int x, int q) { return x; }; - SegmentTree2D s1(mat, 0, f, g, f), - s2(mat, 0, f, g, f); - - queue>> q; - while (Q--) { - int t, c, h, w; - cin >> t >> c >> h >> w; - h--, w--; - while (q.size() and q.front().first <= t) { - int x, y; - tie(x, y) = q.front().second; - mat[x][y] = 2; - s1.update(x, y, 0); - s2.update(x, y, 1); - q.pop(); - } - if (c == 0) { - mat[h][w] = 1; - s1.update(h, w, 1); - q.emplace(t + T, make_pair(h, w)); - } - if (c == 1) { - if (mat[h][w] == 2) { - mat[h][w] = 0; - s2.update(h, w, 0); - } - } - if (c == 2) { - int h2, w2; - cin >> h2 >> w2; - int m = s2.get(h, h2, w, w2, -1); - int n = s1.get(h, h2, w, w2, -1); - printf("%d %d\n", m, n); - } - } -}