From 9eb0ee4c9f077ddc3ea3d51b923d9b058fa9dcf8 Mon Sep 17 00:00:00 2001 From: manoflearning <77jwk0724@gmail.com> Date: Wed, 14 Jan 2026 00:09:49 +0900 Subject: [PATCH 1/2] refactor: drop build() in favor of init() --- src/1-ds/ds_fenwick.cpp | 35 ++------------ src/1-ds/ds_segtree.cpp | 53 +++++++------------- src/1-ds/ds_segtree_pst.cpp | 78 ++++++++++-------------------- src/3-tree/tree_hld.cpp | 3 +- tests/1-ds/test_ds_fenwick.cpp | 15 +++--- tests/1-ds/test_ds_segtree.cpp | 30 +++++++----- tests/1-ds/test_ds_segtree_pst.cpp | 44 ++++++++--------- 7 files changed, 96 insertions(+), 162 deletions(-) diff --git a/src/1-ds/ds_fenwick.cpp b/src/1-ds/ds_fenwick.cpp index be3cfc2..74ea81e 100644 --- a/src/1-ds/ds_fenwick.cpp +++ b/src/1-ds/ds_fenwick.cpp @@ -1,9 +1,9 @@ #include "../0-common/common.hpp" // what: maintain prefix sums with point updates and range sum queries. -// time: build O(n), update/query O(log n); memory: O(n) +// time: init O(n), update/query O(log n); memory: O(n) // constraint: 1-indexed [1, n]; a[0] unused; kth needs all values >= 0. -// usage: fenwick fw; fw.build(a); fw.add(p, x); fw.sum(l, r); fw.kth(k); +// usage: fenwick fw; fw.init(n); fw.add(p, x); fw.set(p, v); fw.sum(l, r); fw.kth(k); struct fenwick { int n; vector a, t; @@ -13,16 +13,6 @@ struct fenwick { a.assign(n + 1, 0); t.assign(n + 1, 0); } - void build(const vector &v) { - // goal: build fenwick in O(n) from initial array. - n = sz(v) - 1; - a = v; - t = a; - for (int i = 1; i <= n; i++) { - int j = i + (i & -i); - if (j <= n) t[j] += t[i]; - } - } void add(int p, ll val) { // goal: a[p] += val. a[p] += val; @@ -79,9 +69,9 @@ struct fenw_range { // 1-indexed }; // what: 2D point updates with axis-aligned rectangle sum queries. -// time: build O(n m), update/query O(log n log m); memory: O(n m) +// time: init O(n m), update/query O(log n log m); memory: O(n m) // constraint: 1-indexed [1..n] x [1..m]; a[0][*], a[*][0] unused; no bounds check. -// usage: fenw_2d fw; fw.build(a); fw.add(x, y, v); fw.sum(x1, y1, x2, y2); +// usage: fenw_2d fw; fw.init(n, m); fw.add(x, y, v); fw.set(x, y, val); fw.sum(x1, y1, x2, y2); struct fenw_2d { // 1-indexed int n, m; vector> a, t; @@ -91,23 +81,6 @@ struct fenw_2d { // 1-indexed a.assign(n + 1, vector(m + 1, 0)); t.assign(n + 1, vector(m + 1, 0)); } - void build(const vector> &v) { - // goal: build 2D fenwick in O(n*m). - n = sz(v) - 1; - m = n ? sz(v[1]) - 1 : 0; - a = v; - t = a; - for (int i = 1; i <= n; i++) - for (int j = 1; j <= m; j++) { - int nj = j + (j & -j); - if (nj <= m) t[i][nj] += t[i][j]; - } - for (int j = 1; j <= m; j++) - for (int i = 1; i <= n; i++) { - int ni = i + (i & -i); - if (ni <= n) t[ni][j] += t[i][j]; - } - } void add(int x, int y, ll val) { // goal: a[x][y] += val. a[x][y] += val; diff --git a/src/1-ds/ds_segtree.cpp b/src/1-ds/ds_segtree.cpp index ce605c3..9ee5f4f 100644 --- a/src/1-ds/ds_segtree.cpp +++ b/src/1-ds/ds_segtree.cpp @@ -1,20 +1,17 @@ #include "../0-common/common.hpp" // what: point update + range sum on a fixed-size array using a tree. -// time: build O(n), update/query O(log n); memory: O(n) +// time: init O(n), update/query O(log n); memory: O(n) // constraint: 1-indexed [1, n]; a[0] unused. -// usage: seg_tree st; st.build(a); st.set(p, v); st.query(l, r); +// usage: seg_tree st; st.init(n); st.set(p, v); st.query(l, r); struct seg_tree { int flag; vector t; - void build(const vector &a) { - // goal: build tree from 1-indexed array. - int n = sz(a) - 1; + void init(int n) { + // goal: allocate tree for size n (all zeros). flag = 1; while (flag < n) flag <<= 1; t.assign(2 * flag, 0); - for (int i = 1; i <= n; i++) t[flag + i - 1] = a[i]; - for (int i = flag - 1; i >= 1; i--) t[i] = t[i << 1] + t[i << 1 | 1]; } void set(int p, ll val) { // goal: set a[p] = val. @@ -31,18 +28,16 @@ struct seg_tree { }; // what: iterative segment tree for point update and range sum. -// time: build O(n), update/query O(log n); memory: O(n) +// time: init O(n), update/query O(log n); memory: O(n) // constraint: 1-indexed [1, n]; a[0] unused. -// usage: seg_tree_it st; st.build(a); st.set(p, v); st.query(l, r); +// usage: seg_tree_it st; st.init(n); st.set(p, v); st.query(l, r); struct seg_tree_it { // 1-indexed int n; vector t; - void build(const vector &a) { - // goal: build tree from 1-indexed array. - n = sz(a) - 1; + void init(int n_) { + // goal: allocate tree for size n (all zeros). + n = n_; t.assign(2 * n, 0); - for (int i = 1; i <= n; i++) t[n + i - 1] = a[i]; - for (int i = n - 1; i >= 1; i--) t[i] = t[i << 1] + t[i << 1 | 1]; } void set(int p, ll val) { // goal: set a[p] = val. @@ -86,21 +81,18 @@ struct seg_tree_kth { }; // what: range add and range sum with lazy propagation. -// time: update/query O(log n); memory: O(n) +// time: init O(n), update/query O(log n); memory: O(n) // constraint: 1-indexed [1, n]; a[0] unused. -// usage: seg_tree_lz st; st.build(a); st.add(l, r, v); st.query(l, r); +// usage: seg_tree_lz st; st.init(n); st.add(l, r, v); st.query(l, r); struct seg_tree_lz { int flag; vector t, lz; - void build(const vector &a) { - // goal: build tree and clear lazy tags. - int n = sz(a) - 1; + void init(int n) { + // goal: allocate tree and clear lazy tags (all zeros). flag = 1; while (flag < n) flag <<= 1; t.assign(2 * flag, 0); lz.assign(2 * flag, 0); - for (int i = 1; i <= n; i++) t[flag + i - 1] = a[i]; - for (int i = flag - 1; i >= 1; i--) t[i] = t[i << 1] + t[i << 1 | 1]; } void add(int l, int r, ll val) { add(l, r, val, 1, 1, flag); } ll query(int l, int r) { return query(l, r, 1, 1, flag); } @@ -182,25 +174,16 @@ struct seg_sparse { }; // what: 2D point updates with rectangle sum queries on a square grid. -// time: build O(n^2), update/query O(log^2 n); memory: O(n^2) +// time: init O(n^2), update/query O(log^2 n); memory: O(n^2) // constraint: 1-indexed square [1..n] x [1..n]; a[0][*], a[*][0] unused. -// usage: seg_2d st; st.build(a); st.set(x, y, v); st.query(x1, x2, y1, y2); +// usage: seg_2d st; st.init(n); st.set(x, y, v); st.query(x1, x2, y1, y2); struct seg_2d { // 1-indexed int n; vector> t; - void build(const vector> &a) { - // goal: build 2D tree from initial grid. - n = sz(a) - 1; + void init(int n_) { + // goal: allocate 2D tree (all zeros). + n = n_; t.assign(2 * n, vector(2 * n, 0)); - for (int i = 1; i <= n; i++) - for (int j = 1; j <= n; j++) - t[i + n - 1][j + n - 1] = a[i][j]; - for (int i = n; i < 2 * n; i++) - for (int j = n - 1; j > 0; j--) - t[i][j] = t[i][j << 1] + t[i][j << 1 | 1]; - for (int i = n - 1; i > 0; i--) - for (int j = 1; j < 2 * n; j++) - t[i][j] = t[i << 1][j] + t[i << 1 | 1][j]; } void set(int x, int y, ll val) { // goal: set a[x][y] = val. diff --git a/src/1-ds/ds_segtree_pst.cpp b/src/1-ds/ds_segtree_pst.cpp index ed5621b..ab755a4 100644 --- a/src/1-ds/ds_segtree_pst.cpp +++ b/src/1-ds/ds_segtree_pst.cpp @@ -1,9 +1,9 @@ #include "../0-common/common.hpp" // what: persistent segment tree for point set with range sum queries, plus kth by prefix sum. -// time: build O(n), update/query O(log n); memory: O(n log n) -// constraint: 1-indexed [1, n]; a[0] unused; kth needs all values >= 0. -// usage: seg_pst st; st.build(n, a); st.set(p, v); st.query(l, r, ver); st.kth(k, ver); +// time: init O(1), update/query/kth O(log n); memory: O(q log n) +// constraint: version 0 is all zeros; 1-indexed [1, n]; kth needs all values >= 0. +// usage: seg_pst st; st.init(n); st.set(p, v); st.query(l, r, ver); st.kth(k, ver); struct seg_pst { struct node { int l, r; @@ -13,64 +13,36 @@ struct seg_pst { vector t; vector root; - void newnd() { t.push_back({-1, -1, 0}); } - void build(int n_, const vector &a) { - // goal: build initial version. + int newnd(const node &nd) { + t.push_back(nd); + return sz(t) - 1; + } + void init(int n_) { + // goal: version 0 = all zeros (root = 0). n = n_; - t.clear(); - root.clear(); - newnd(); - root.push_back(0); - build(1, n, root[0], a); + t.assign(1, {0, 0, 0}); + root.assign(1, 0); } - void build(int l, int r, int v, const vector &a) { - // goal: build node v for range [l, r]. - if (l == r) { - t[v].val = a[l]; - return; + int set(int p, ll val, int nl, int nr, int v) { + // goal: update along path while sharing unchanged nodes. + int u = newnd(t[v]); + if (nl == nr) { + t[u].val = val; + return u; } - newnd(); - t[v].l = sz(t) - 1; - newnd(); - t[v].r = sz(t) - 1; - int mid = (l + r) >> 1; - build(l, mid, t[v].l, a); - build(mid + 1, r, t[v].r, a); - t[v].val = t[t[v].l].val + t[t[v].r].val; + int mid = (nl + nr) >> 1; + if (p <= mid) t[u].l = set(p, val, nl, mid, t[v].l); + else t[u].r = set(p, val, mid + 1, nr, t[v].r); + t[u].val = t[t[u].l].val + t[t[u].r].val; + return u; } void set(int p, ll val) { - // goal: create new version with a[p] = val. - newnd(); - root.push_back(sz(t) - 1); - set(p, val, 1, n, root[sz(root) - 2], root.back()); - } - void set(int p, ll val, int l, int r, int v1, int v2) { - // goal: update along path while sharing unchanged nodes. - if (p < l || r < p) { - t[v2] = t[v1]; - return; - } - if (l == r) { - t[v2].val = val; - return; - } - int mid = (l + r) >> 1; - if (p <= mid) { - t[v2].r = t[v1].r; - newnd(); - t[v2].l = sz(t) - 1; - set(p, val, l, mid, t[v1].l, t[v2].l); - } else { - t[v2].l = t[v1].l; - newnd(); - t[v2].r = sz(t) - 1; - set(p, val, mid + 1, r, t[v1].r, t[v2].r); - } - t[v2].val = t[t[v2].l].val + t[t[v2].r].val; + // goal: create new version from last with a[p] = val. + root.push_back(set(p, val, 1, n, root.back())); } ll query(int l, int r, int v, int nl, int nr) const { // result: sum on [l, r] in a specific version. - if (r < nl || nr < l) return 0; + if (v == 0 || r < nl || nr < l) return 0; if (l <= nl && nr <= r) return t[v].val; int mid = (nl + nr) >> 1; return query(l, r, t[v].l, nl, mid) + query(l, r, t[v].r, mid + 1, nr); diff --git a/src/3-tree/tree_hld.cpp b/src/3-tree/tree_hld.cpp index 52e63e1..fe96ba9 100644 --- a/src/3-tree/tree_hld.cpp +++ b/src/3-tree/tree_hld.cpp @@ -51,8 +51,7 @@ struct hld_tree { void build(int root = 1) { dfs_sz(root, 0); dfs_hld(root, root); - vector a(n + 1, 0); - seg.build(a); + seg.init(n); } void set(int v, ll val) { seg.set(in[v], val); } ll query(int a, int b) const { diff --git a/tests/1-ds/test_ds_fenwick.cpp b/tests/1-ds/test_ds_fenwick.cpp index a8e5823..c0559ff 100644 --- a/tests/1-ds/test_ds_fenwick.cpp +++ b/tests/1-ds/test_ds_fenwick.cpp @@ -35,8 +35,8 @@ ll sum_2d(const vector> &a, int x1, int y1, int x2, int y2) { void test_fenwick_basic() { fenwick fw; - vector a = {0, 5}; - fw.build(a); + fw.init(1); + fw.set(1, 5); assert(fw.sum(1, 1) == 5); assert(fw.kth(1) == 1); fw.set(1, 0); @@ -51,7 +51,8 @@ void test_fenwick_random() { for (int i = 1; i <= n; i++) a[i] = rnd(0, 5); fenwick fw; - fw.build(a); + fw.init(n); + for (int i = 1; i <= n; i++) fw.add(i, a[i]); for (int it = 0; it < 5000; it++) { int op = (int)rnd(0, 3); @@ -109,8 +110,8 @@ void test_fenwick_rp_random() { void test_fenwick_2d_basic() { fenw_2d fw; - vector> a = {{0, 0}, {0, 3}}; - fw.build(a); + fw.init(1, 1); + fw.set(1, 1, 3); assert(fw.sum(1, 1, 1, 1) == 3); fw.set(1, 1, -2); assert(fw.sum(1, 1, 1, 1) == -2); @@ -123,7 +124,9 @@ void test_fenwick_2d_random() { for (int j = 1; j <= m; j++) a[i][j] = rnd(-3, 3); fenw_2d fw; - fw.build(a); + fw.init(n, m); + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) fw.add(i, j, a[i][j]); for (int it = 0; it < 4000; it++) { int op = (int)rnd(0, 2); diff --git a/tests/1-ds/test_ds_segtree.cpp b/tests/1-ds/test_ds_segtree.cpp index ebf5d81..1934930 100644 --- a/tests/1-ds/test_ds_segtree.cpp +++ b/tests/1-ds/test_ds_segtree.cpp @@ -27,9 +27,9 @@ int kth_naive_freq(const vector &a, ll k) { } void test_segt_basic() { - vector a = {0, 3}; seg_tree st; - st.build(a); + st.init(1); + st.set(1, 3); assert(st.query(1, 1) == 3); st.set(1, -2); assert(st.query(1, 1) == -2); @@ -41,7 +41,8 @@ void test_segt_random() { for (int i = 1; i <= n; i++) a[i] = rnd(-5, 5); seg_tree st; - st.build(a); + st.init(n); + for (int i = 1; i <= n; i++) st.set(i, a[i]); for (int it = 0; it < 5000; it++) { int op = (int)rnd(0, 1); @@ -59,9 +60,9 @@ void test_segt_random() { } void test_segti_basic() { - vector a = {0, 4}; seg_tree_it st; - st.build(a); + st.init(1); + st.set(1, 4); assert(st.query(1, 1) == 4); st.set(1, 1); assert(st.query(1, 1) == 1); @@ -73,7 +74,8 @@ void test_segti_random() { for (int i = 1; i <= n; i++) a[i] = rnd(-5, 5); seg_tree_it st; - st.build(a); + st.init(n); + for (int i = 1; i <= n; i++) st.set(i, a[i]); for (int it = 0; it < 5000; it++) { int op = (int)rnd(0, 1); @@ -125,9 +127,10 @@ void test_segk_random() { } void test_seglz_basic() { - vector a = {0, 1, 2}; seg_tree_lz st; - st.build(a); + st.init(2); + st.add(1, 1, 1); + st.add(2, 2, 2); st.add(1, 2, 3); assert(st.query(1, 2) == 1 + 2 + 6); } @@ -138,7 +141,8 @@ void test_seglz_random() { for (int i = 1; i <= n; i++) a[i] = rnd(-5, 5); seg_tree_lz st; - st.build(a); + st.init(n); + for (int i = 1; i <= n; i++) st.add(i, i, a[i]); for (int it = 0; it < 4000; it++) { int op = (int)rnd(0, 1); @@ -196,9 +200,9 @@ ll sum_rect(const vector> &a, int x1, int y1, int x2, int y2) { } void test_seg2d_basic() { - vector> a = {{0, 0}, {0, 7}}; seg_2d st; - st.build(a); + st.init(1); + st.set(1, 1, 7); assert(st.query(1, 1, 1, 1) == 7); st.set(1, 1, -1); assert(st.query(1, 1, 1, 1) == -1); @@ -211,7 +215,9 @@ void test_seg2d_random() { for (int j = 1; j <= n; j++) a[i][j] = rnd(-3, 3); seg_2d st; - st.build(a); + st.init(n); + for (int i = 1; i <= n; i++) + for (int j = 1; j <= n; j++) st.set(i, j, a[i][j]); for (int it = 0; it < 3000; it++) { int op = (int)rnd(0, 1); diff --git a/tests/1-ds/test_ds_segtree_pst.cpp b/tests/1-ds/test_ds_segtree_pst.cpp index 7b91924..4c0fb43 100644 --- a/tests/1-ds/test_ds_segtree_pst.cpp +++ b/tests/1-ds/test_ds_segtree_pst.cpp @@ -28,23 +28,22 @@ int kth_naive_freq(const vector &a, ll k) { void test_pst_basic() { int n = 3; - vector a = {0, 1, 2, 3}; seg_pst st; - st.build(n, a); + st.init(n); + st.set(1, 1); + st.set(2, 2); + st.set(3, 3); st.set(2, 5); - assert(st.query(1, 3, 0) == 6); - assert(st.query(1, 3, 1) == 9); + assert(st.query(1, 3, 3) == 6); + assert(st.query(1, 3, 4) == 9); } void test_pst_random() { int n = 20; vector> ver; - vector a(n + 1, 0); - for (int i = 1; i <= n; i++) a[i] = rnd(-5, 5); - ver.push_back(a); - seg_pst st; - st.build(n, a); + st.init(n); + ver.push_back(vector(n + 1, 0)); for (int it = 0; it < 2000; it++) { int op = (int)rnd(0, 1); @@ -66,29 +65,28 @@ void test_pst_random() { void test_pst_kth_basic() { int n = 5; - vector a = {0, 2, 0, 1, 3, 0}; seg_pst st; - st.build(n, a); - assert(st.kth(1, 0) == 1); - assert(st.kth(2, 0) == 1); - assert(st.kth(3, 0) == 3); - assert(st.kth(6, 0) == 4); + st.init(n); + st.set(1, 2); + st.set(3, 1); + st.set(4, 3); + assert(st.kth(1, 3) == 1); + assert(st.kth(2, 3) == 1); + assert(st.kth(3, 3) == 3); + assert(st.kth(6, 3) == 4); st.set(2, 4); - assert(st.kth(3, 1) == 2); - assert(st.kth(10, 1) == 4); + assert(st.kth(3, 4) == 2); + assert(st.kth(10, 4) == 4); st.set(4, 0); - assert(st.kth(7, 2) == 3); + assert(st.kth(7, 5) == 3); } void test_pst_kth_random() { int n = 40; vector> ver; - vector a(n + 1, 0); - for (int i = 1; i <= n; i++) a[i] = rnd(0, 3); - ver.push_back(a); - seg_pst st; - st.build(n, a); + st.init(n); + ver.push_back(vector(n + 1, 0)); for (int it = 0; it < 2000; it++) { int op = (int)rnd(0, 1); From 709f9389fdbe35ebe46335d4ef591e64849edb6b Mon Sep 17 00:00:00 2001 From: manoflearning <77jwk0724@gmail.com> Date: Wed, 14 Jan 2026 00:27:33 +0900 Subject: [PATCH 2/2] refactor: move kth into seg_tree --- src/1-ds/ds_segtree.cpp | 44 +++++++++++----------------------- tests/1-ds/test_ds_segtree.cpp | 15 ++++++------ 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/1-ds/ds_segtree.cpp b/src/1-ds/ds_segtree.cpp index 9ee5f4f..d282da7 100644 --- a/src/1-ds/ds_segtree.cpp +++ b/src/1-ds/ds_segtree.cpp @@ -1,9 +1,9 @@ #include "../0-common/common.hpp" -// what: point update + range sum on a fixed-size array using a tree. -// time: init O(n), update/query O(log n); memory: O(n) -// constraint: 1-indexed [1, n]; a[0] unused. -// usage: seg_tree st; st.init(n); st.set(p, v); st.query(l, r); +// what: point update + range sum on a fixed-size array, plus kth by prefix sum. +// time: init O(n), update/query/kth O(log n); memory: O(n) +// constraint: 1-indexed [1, n]; a[0] unused; kth needs all values >= 0. +// usage: seg_tree st; st.init(n); st.set(p, v); st.query(l, r); st.kth(k); struct seg_tree { int flag; vector t; @@ -25,6 +25,16 @@ struct seg_tree { int mid = (nl + nr) >> 1; return query(l, r, v << 1, nl, mid) + query(l, r, v << 1 | 1, mid + 1, nr); } + int kth(ll k) const { + // result: smallest idx with prefix sum >= k. + assert(k > 0 && t[1] >= k); + int v = 1; + while (v < flag) { + if (k <= t[v << 1]) v <<= 1; + else k -= t[v << 1], v = v << 1 | 1; + } + return v - flag + 1; + } }; // what: iterative segment tree for point update and range sum. @@ -54,32 +64,6 @@ struct seg_tree_it { // 1-indexed } }; -// what: find k-th element by prefix sum on a frequency array. -// time: update/query O(log n); memory: O(n) -// constraint: 1-indexed [1, n], values >= 0. -// usage: seg_tree_kth st; st.init(n); st.add(p, v); st.kth(k); -struct seg_tree_kth { - int flag; - vector t; - void init(int n) { - // goal: allocate tree for size n. - flag = 1; - while (flag < n) flag <<= 1; - t.assign(flag << 1, 0); - } - void add(int p, ll val) { - // goal: add val to frequency at p. - for (t[p += flag - 1] += val; p > 1; p >>= 1) t[p >> 1] = t[p] + t[p ^ 1]; - } - ll kth(ll k, int v = 1) const { - // result: smallest index with prefix sum >= k. - assert(t[v] >= k); - if (v >= flag) return v - flag + 1; - if (k <= t[v << 1]) return kth(k, v << 1); - return kth(k - t[v << 1], v << 1 | 1); - } -}; - // what: range add and range sum with lazy propagation. // time: init O(n), update/query O(log n); memory: O(n) // constraint: 1-indexed [1, n]; a[0] unused. diff --git a/tests/1-ds/test_ds_segtree.cpp b/tests/1-ds/test_ds_segtree.cpp index 1934930..c2d423f 100644 --- a/tests/1-ds/test_ds_segtree.cpp +++ b/tests/1-ds/test_ds_segtree.cpp @@ -1,6 +1,6 @@ #include "../../src/1-ds/ds_segtree.cpp" -// what: tests for seg_tree, seg_tree_it, seg_tree_kth, seg_tree_lz, seg_sparse, seg_2d, seg2d_comp. +// what: tests for seg_tree, seg_tree_it, seg_tree_lz, seg_sparse, seg_2d, seg2d_comp. // time: random + edge cases; memory: O(n log n) // constraint: uses assert, fixed seed. // usage: g++ -std=c++17 test_ds_segtree.cpp && ./a.out @@ -94,10 +94,10 @@ void test_segti_random() { void test_segk_basic() { int n = 3; - seg_tree_kth st; + seg_tree st; st.init(n); - st.add(1, 2); - st.add(3, 1); + st.set(1, 2); + st.set(3, 1); assert(st.kth(1) == 1); assert(st.kth(2) == 1); assert(st.kth(3) == 3); @@ -106,16 +106,17 @@ void test_segk_basic() { void test_segk_random() { int n = 40; vector a(n + 1, 0); - seg_tree_kth st; + seg_tree st; st.init(n); for (int it = 0; it < 4000; it++) { int op = (int)rnd(0, 1); if (op == 0) { int p = (int)rnd(1, n); - ll v = rnd(0, 3); + ll v = rnd(-3, 3); + if (a[p] + v < 0) continue; a[p] += v; - st.add(p, v); + st.set(p, a[p]); } else { ll tot = 0; for (int i = 1; i <= n; i++) tot += a[i];