diff --git a/algorithms/structure/lazy_segment_tree.cpp b/algorithms/structure/lazy_segment_tree.cpp index 5b8f4d0bc0667742af7c9a346919a8553d4586bf..22f063faa672b45435f977e1a61222c2391cc04f 100644 --- a/algorithms/structure/lazy_segment_tree.cpp +++ b/algorithms/structure/lazy_segment_tree.cpp @@ -1,52 +1,43 @@ /// Lazy Segment Tree /// /// Time: -/// - build_tree: O(n log n) -/// - update_tree: O(log n) -/// - query_tree: O(log n) +/// - build: O(n log n) +/// - update: O(log n) +/// - query: O(log n) /// Space: O(n) -int N; -struct LazySegmentTree { - vector<int> tree, lazy; +#define left(x) (x << 1) +#define right(x) ((x << 1) + 1) - LazySegmentTree(const vector<int> &v) : - tree(MAX*4), lazy(MAX*4) - { - init(); - build(v); - } +int N; - void init() { - fill(all(tree), 0); - fill(all(lazy), 0); - } +template <typename T> +struct LazySegmentTree { + vector<T> tree, lazy; - inline int left(int x) { return (x << 1); } - inline int right(int x) { return (x << 1) + 1; } + LazySegmentTree(const vector<T> &v) : + tree(MAX*4, 0), lazy(MAX*4, 0) + { build(v); } - void build(const vector<int> &v, int node = 1, - int a = 0, int b = N - 1) + void build(const vector<T> &v, + int node = 1, int l = 0, int r = N - 1) { - if (a > b) - return; - - if (a == b) { - tree[node] = v[a]; - return; + if (l > r) return; + + if (l == r) + tree[node] = v[l]; + else { + int m = (l + r) / 2; + build(v, left(node), l, m); + build(v, right(node), m + 1, r); + tree[node] = tree[left(node)] + tree[right(node)]; } - - int mid = (a + b) / 2; - build(v, left(node), a, mid); - build(v, right(node), mid + 1, b); - tree[node] = tree[left(node)] + tree[right(node)]; } - void push(int node, int a, int b, int val) { - tree[node] += val; - // tree[node] += (b - a + 1)*val; (for Range Sum Query) + void push(int node, int l, int r, T val) { + tree[node] += (r - l + 1)*val; - if (a != b) { + if (l != r) { lazy[left(node)] += val; lazy[right(node)] += val; } @@ -54,41 +45,38 @@ struct LazySegmentTree { lazy[node] = 0; } - void update(int i, int j, int val, int node = 1, - int a = 0, int b = N - 1) + void update(int i, int j, T val, + int node = 1, int l = 0, int r = N - 1) { if (lazy[node] != 0) - push(node, a, b, lazy[node]); + push(node, l, r, lazy[node]); - if (a > b || a > j || b < i) - return; + if (l > r || l > j || r < i) return; - if (i <= a && b <= j) { - push(node, a, b, val); - return; + if (i <= l && r <= j) + push(node, l, r, val); + else { + int m = (l + r) / 2; + update(i, j, val, left(node), l, m); + update(i, j, val, right(node), m + 1, r); + tree[node] = tree[left(node)] + tree[right(node)]; } - - int mid = (a + b) / 2; - update(i, j, val, left(node), a, mid); - update(i, j, val, right(node), mid + 1, b); - tree[node] = tree[left(node)] + tree[right(node)]; } - int query(int i, int j, int node = 1, - int a = 0, int b = N - 1) + T query(int i, int j, + int node = 1, int l = 0, int r = N - 1) { - if (a > b || a > j || b < i) - return 0; + if (l > r || l > j || r < i) return 0; if (lazy[node]) - push(node, a, b, lazy[node]); + push(node, l, r, lazy[node]); - if (a >= i && b <= j) + if (l >= i && r <= j) return tree[node]; - int mid = (a + b) / 2; - int q1 = query(i, j, left(node), a, mid); - int q2 = query(i, j, right(node), mid + 1, b); + int m = (l + r) / 2; + T q1 = query(i, j, left(node), l, m); + T q2 = query(i, j, right(node), m + 1, r); return q1 + q2; } }; diff --git a/algorithms/structure/policy_tree.cpp b/algorithms/structure/policy_tree.cpp index e421ffa08ce53a1ac89f61a5c68a5b906a222f98..9e06d9b8d4b0e2ca627bb863c440c90ed1569bc1 100644 --- a/algorithms/structure/policy_tree.cpp +++ b/algorithms/structure/policy_tree.cpp @@ -12,24 +12,20 @@ #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> - using namespace __gnu_pbds; -typedef tree< - int, - null_type, - less<int>, - rb_tree_tag, - tree_order_statistics_node_update -> set_t; +template <typename T> +using ordered_set = + tree<T, null_type, less<T>, rb_tree_tag, + tree_order_statistics_node_update>; void operations() { - set_t S; + ordered_set S; S.insert(x); S.erase(x); - // Return iterator to the k-th largest element + // Return iordered_set terator to the k-th largest element // (counting from zero) int pos = *S.find_by_order(k); diff --git a/algorithms/structure/segment_tree.cpp b/algorithms/structure/segment_tree.cpp index b889aae5ab41c692467945c4471b2f7ce3917e65..b2ee9399498df82219892276be3a859111d68ae4 100644 --- a/algorithms/structure/segment_tree.cpp +++ b/algorithms/structure/segment_tree.cpp @@ -10,20 +10,19 @@ /// - Provide identity value if necessary (default is T()) // Example: SegmentTree<int,plus<int>> seg(n) -template <typename T, typename OpType = T(*)(T&, T&)> +template <typename T, typename OT = T(*)(T&, T&)> struct SegmentTree { int N; T ident; - OpType op; + OT op; vector<T> tree; - SegmentTree(int N, T ident = T()) : - N(N), ident(ident), tree(2 * N, ident) {} + SegmentTree(int N, T id = T()) : + N(N), ident(id), tree(2 * N, id) {} void update(int idx, T val) { idx += N; tree[idx] = val; - for (; idx > 1; idx >>= 1) tree[idx >> 1] = op(tree[idx & ~1], tree[idx | 1]); } @@ -31,12 +30,10 @@ struct SegmentTree { T query(int l, int r) { T ra = ident, rb = ident; l += N, r += N; - for (; l < r; l >>= 1, r >>= 1) { if (l & 1) ra = op(ra, tree[l++]); if (r & 1) rb = op(tree[--r], rb); } - return op(ra, rb); } }; diff --git a/algorithms/structure/segment_tree_2d.cpp b/algorithms/structure/segment_tree_2d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbe716ba211a0d9df6a3ded2bc2a72e305fdb497 --- /dev/null +++ b/algorithms/structure/segment_tree_2d.cpp @@ -0,0 +1,112 @@ +/// 2D Segment Tree +/// +/// Time: +/// - build: O(n * m * log n * log m) +/// - update: O(log n * log m) +/// - query: O(log n * log m) +/// Space: O(16 * n * m) +/// +/// Caution: +/// - Very high constant in space complexity + +#define left(x) (x << 1) +#define right(x) ((x << 1) + 1) + +int N, M; + +template<typename T> +struct SegmentTree2D { + vector<vector<T>> tree; + + SegmentTree2D(const vector<vector<T>> &mat) : + tree(4*MAX, vector<T>(4*MAX, 0)) + { build(mat); } + + void build_row(const vector<vector<T>> &mat, + int ni, int li, int ri, + int nj = 1, int lj = 0, int rj = M - 1) + { + if (lj == rj) { + if (li == ri) + tree[ni][nj] = mat[li][lj]; + else + tree[ni][nj] = tree[left(ni)][nj] + tree[right(ni)][nj]; + } else { + int m = (lj + rj) / 2; + build_row(mat, ni, li, ri, left(nj), lj, m); + build_row(mat, ni, li, ri, right(nj), m+1, rj); + tree[ni][nj] = tree[ni][left(nj)] + tree[ni][right(nj)]; + } + } + + void build(const vector<vector<T>> &mat, + int ni = 1, int li = 0, int ri = N - 1) + { + if (li != ri) { + int m = (li + ri) / 2; + build(mat, left(ni), li, m); + build(mat, right(ni), m+1, ri); + } + build_row(mat, ni, li, ri); + } + + T query_row(int j1, int j2, int i, + int nj = 1, int lj = 0, int rj = M - 1) + { + if (lj > rj || lj > j2 || rj < j1) return 0; + + if (j1 <= lj && rj <= j2) + return tree[i][nj]; + + int m = (lj + rj) / 2; + T q1 = query_row(j1, j2, i, left(nj), lj, m); + T q2 = query_row(j1, j2, i, right(nj), m + 1, rj); + return q1 + q2; + } + + T query(int i1, int j1, int i2, int j2, + int ni = 1, int li = 0, int ri = N - 1) + { + if (li > ri || li > i2 || ri < i1) return 0; + + if (i1 <= li && ri <= i2) + return query_row(j1, j2, ni); + + int m = (li + ri) / 2; + T q1 = query(i1, j1, i2, j2, left(ni), li, m); + T q2 = query(i1, j1, i2, j2, right(ni), m + 1, ri); + return q1 + q2; + } + + void update_row(int i, int j, T val, + int ni, int li, int ri, + int nj = 1, int lj = 0, int rj = M - 1) + { + if (lj > rj || lj > j || rj < j) return; + + if (lj == rj) { + if (li == ri) + tree[ni][nj] = val; + else + tree[ni][nj] = tree[left(ni)][nj] + tree[right(ni)][nj]; + } else { + int m = (lj + rj) / 2; + update_row(i, j, val, ni, li, ri, left(nj), lj, m); + update_row(i, j, val, ni, li, ri, right(nj), m+1, rj); + tree[ni][nj] = tree[ni][left(nj)] + tree[ni][right(nj)]; + } + } + + void update(int i, int j, T val, + int ni = 1, int li = 0, int ri = N - 1) + { + if (li > ri || li > i || ri < i) return; + + if (li != ri) { + int m = (li + ri) / 2; + update(i, j, val, left(ni), li, m); + update(i, j, val, right(ni), m+1, ri); + } + update_row(i, j, val, ni, li, ri); + } +};