From 1172d4842b4e062795bfa2acaa13e64224cd31c7 Mon Sep 17 00:00:00 2001 From: Lam Haoyin Date: Mon, 4 Apr 2022 18:46:41 +0800 Subject: [PATCH] add: 220404-CN [cpp] --- cpp/2204/220404-CN.cpp | 121 ++++++++++++++++++++++++++++++++++++++++ cpp/2204/CMakeLists.txt | 2 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 cpp/2204/220404-CN.cpp diff --git a/cpp/2204/220404-CN.cpp b/cpp/2204/220404-CN.cpp new file mode 100644 index 0000000..cd36cde --- /dev/null +++ b/cpp/2204/220404-CN.cpp @@ -0,0 +1,121 @@ +#include +#include +#include + +/** + * 307. Range Sum Query - Mutable + * Given an integer array nums, handle multiple queries of the following types: + * + * Update the value of an element in nums. + * Calculate the sum of the elements of nums between indices left and right inclusive where left <= right. + * Implement the NumArray class: + * + * NumArray(int[] nums) Initializes the object with the integer array nums. + * void update(int index, int val) Updates the value of nums[index] to be val. + * int sumRange(int left, int right) Returns the sum of the elements of nums between indices left and right inclusive (i.e. nums[left] + nums[left + 1] + ... + nums[right]). + */ + +#ifdef GENERIC +#include +#ifdef LOCAL +template +#endif +class NumArray { +private: +#ifndef LOCAL + static inline const int maxCacheSize = 192; +#endif + std::vector n; + + std::vector prefixSum; + + std::map alterCache; +public: + explicit NumArray(std::vector nums) : n(std::move(nums)) { + prefixSum.reserve(n.size()); + int s = 0; + for (int x : n) { + s += x; + prefixSum.push_back(s); + } + } + + void update(int index, int val); + + int sumRange(int left, int right) const; +}; + +void NumArray::update(int index, int val) { + alterCache[index] = val; + if (alterCache.size() < maxCacheSize) + return; + int offset = 0, nSize = n.size(); + for (auto it = std::next(alterCache.cbegin()); it != alterCache.cend(); ++it) { + auto itPrev = std::prev(it); + offset += itPrev->second - n[itPrev->first]; + for (int i = itPrev->first; i < it->first; ++i) + prefixSum[i] += offset; + } + offset += alterCache.crbegin()->second - n[alterCache.crbegin()->first]; + for (int i = alterCache.crbegin()->first; i < nSize; ++i) + prefixSum[i] += offset; + for (const auto& [i, v] : alterCache) + n[i] = v; + alterCache.clear(); +} + +int NumArray::sumRange(int left, int right) const { + int result = prefixSum[right] - (left > 0 ? prefixSum[left - 1] : 0); + for (const auto& [i, v] : alterCache) + if (i >= left && i <= right) + result += v - n[i]; + return result; +} +#endif // GENERIC + +// Segment Tree +#ifndef GENERIC +class NumArray { +private: + static inline const int maxSizeBit = 15; + static inline const int maxSize = 1 << maxSizeBit; + + int segTree[maxSize << 1]; + + int n; +public: + explicit NumArray(const std::vector& nums) { + n = nums.size(); + for (int i = 0; i < n; ++i) + segTree[i + maxSize] = nums[i]; + // Build + for (int i = maxSize >> 1; i; i >>= 1) + for (int j = i; j < (i << 1); ++j) + segTree[j] = segTree[j << 1] + segTree[1 + (j << 1)]; + } + + void update(int index, int val) { + int offset = val - segTree[index + maxSize]; + for (int i = index + maxSize; i; i >>= 1) + segTree[i] += offset; + } + + int sumRange(int left, int right) const { + std::function query = [&](int o, int L, int R) { + int M = L + ((R - L) >> 1), ret = 0; + if (left <= L && R <= right) + return segTree[o]; + if (left <= M) + ret += query(o << 1, L, M); + if (M < right) + ret += query(1 + (o << 1), M + 1, R); + return ret; + }; + return query(1, 0, maxSize - 1); + } +}; +#endif // GENERIC + +int main() { + return 0; +} diff --git a/cpp/2204/CMakeLists.txt b/cpp/2204/CMakeLists.txt index 3b21d97..68c4c84 100644 --- a/cpp/2204/CMakeLists.txt +++ b/cpp/2204/CMakeLists.txt @@ -3,4 +3,4 @@ PROJECT(2204) SET(CMAKE_CXX_STANDARD 23) -ADD_EXECUTABLE(2204 220404.cpp) +ADD_EXECUTABLE(2204 220404-CN.cpp)