diff --git a/algorithms/structure/sqrt_decomposition.cpp b/algorithms/structure/sqrt_decomposition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92e58ceca10bcb2017bd080e41838172fe4eb399 --- /dev/null +++ b/algorithms/structure/sqrt_decomposition.cpp @@ -0,0 +1,62 @@ +/** + * Sqrt Decomposition + * + * Complexity (time): + * Preprocess -> O(n) + * Query -> O(sqrt(n)) + * Update -> O(1) + * Complexity (space): O(n) + */ + +int v[MAX]; +int block[MAX]; +int block_size; + +/** + * Update v[idx] with val. + * @param idx index of v + * @param val new value of v[idx] + */ +void update(int idx, int val) { + block[idx / block_size] += val - v[idx]; + v[idx] = val; +} + +/** + * Range sum query of v[l..r]. + * @param l,r range + */ +int query(int l, int r) { + int ans = 0; + + // Query sum of elements in case l is inside a block + for (; l < r && ((l % block_size) != 0); ++l) + ans += v[l]; + + // Query sum of each block between l and r + for (; l + block_size <= r; l += block_size) + ans += block[l / block_size]; + + // Query sum of remaining blocks (e.g. r is inside a block) + for (; l <= r; ++l) + ans += v[l]; + + return ans; +} + +/** + * Fills block array with necessary data to perform update and query in + * less than linear time. + * @param n number of elements of v + */ +void preprocess(int n) { + block_size = sqrt(n); + + int idx = -1; + for (int i = 0; i < n; ++i) { + if (i % block_size == 0) + block[++idx] = 0; + + block[idx] += v[i]; + } +}