@@ -81,16 +81,26 @@ tags:
8181
8282## 解法
8383
84- <!-- solution:start -->
85-
86- ### 方法一
87-
8884<!-- tabs:start -->
8985
9086#### Python3
9187
9288``` python
93-
89+ class Solution :
90+ def maxSubarraySum (self , nums : List[int ]) -> int :
91+ max_sum = nums[0 ]
92+ min_sum = curr_sum = acc_min = 0
93+ dp = defaultdict(int )
94+ for num in nums:
95+ curr_sum += num
96+ curr = curr_sum - acc_min
97+ if max_sum < curr: max_sum = curr
98+ if num >= 0 : continue
99+ if dp[num] > min_sum: dp[num] = min_sum
100+ dp[num] += num
101+ if acc_min > dp[num]: acc_min = dp[num]
102+ if min_sum > curr_sum: min_sum = curr_sum
103+ return max_sum
94104```
95105
96106#### Java
@@ -102,13 +112,187 @@ tags:
102112#### C++
103113
104114``` cpp
105-
115+ struct T {
116+ long sum;
117+ long maxSubarraySumPrefix;
118+ long maxSubarraySumSuffix;
119+ long maxSubarraySum;
120+ T() = default;
121+ T(int num)
122+ : sum(num),
123+ maxSubarraySumPrefix(num),
124+ maxSubarraySumSuffix(num),
125+ maxSubarraySum(num) {}
126+ T(long sum, long prefix, long suffix, long maxSum)
127+ : sum(sum),
128+ maxSubarraySumPrefix(prefix),
129+ maxSubarraySumSuffix(suffix),
130+ maxSubarraySum(maxSum) {}
131+ };
132+
133+ class SegmentTree {
134+ public:
135+ SegmentTree(const vector<int >& nums) : n(nums.size()), tree(nums.size() * 4) {
136+ build(nums, 0, 0, n - 1);
137+ }
138+
139+ // Updates nums[ i] to val.
140+ void update(int i, int val) {
141+ update(0, 0, n - 1, i, val);
142+ }
143+
144+ long getMaxSubarraySum() const {
145+ return tree[ 0] .maxSubarraySum;
146+ }
147+
148+ private:
149+ const int n; // the size of the input array
150+ vector<T > tree; // the segment tree
151+
152+ void build(const vector<int >& nums, int treeIndex, int lo, int hi) {
153+ if (lo == hi) {
154+ tree[ treeIndex] = T(nums[ lo] );
155+ return;
156+ }
157+ const int mid = (lo + hi) / 2;
158+ build(nums, 2 * treeIndex + 1, lo, mid);
159+ build(nums, 2 * treeIndex + 2, mid + 1, hi);
160+ tree[ treeIndex] = merge(tree[ 2 * treeIndex + 1] , tree[ 2 * treeIndex + 2] );
161+ }
162+
163+ void update(int treeIndex, int lo, int hi, int i, int val) {
164+ if (lo == hi) {
165+ tree[ treeIndex] = T(val);
166+ return;
167+ }
168+ const int mid = (lo + hi) / 2;
169+ if (i <= mid)
170+ update(2 * treeIndex + 1, lo, mid, i, val);
171+ else
172+ update(2 * treeIndex + 2, mid + 1, hi, i, val);
173+ tree[ treeIndex] = merge(tree[ 2 * treeIndex + 1] , tree[ 2 * treeIndex + 2] );
174+ }
175+
176+ T merge(const T& left, const T& right) const {
177+ return T(
178+ left.sum + right.sum,
179+ max(left.maxSubarraySumPrefix, left.sum + right.maxSubarraySumPrefix),
180+ max(right.maxSubarraySumSuffix, right.sum + left.maxSubarraySumSuffix),
181+ max({left.maxSubarraySum, right.maxSubarraySum,
182+ left.maxSubarraySumSuffix + right.maxSubarraySumPrefix}));
183+ }
184+ };
185+
186+ class Solution {
187+ public:
188+ long long maxSubarraySum(vector<int >& nums) {
189+ const bool allPositives =
190+ ranges::all_of(nums, [ ] (int num) { return num >= 0; });
191+ const long sum = accumulate(nums.begin(), nums.end(), 0L);
192+ if (allPositives)
193+ return sum;
194+ const int maxNum = ranges::max(nums);
195+ if (maxNum < 0)
196+ return maxNum;
197+
198+ long ans = LONG_MIN;
199+ unordered_map<int, vector<int>> numToIndices;
200+ SegmentTree tree(nums);
201+
202+ for (int i = 0; i < nums.size(); ++i)
203+ numToIndices[nums[i]].push_back(i);
204+
205+ for (const auto& [num, indices] : numToIndices) {
206+ for (const int index : indices)
207+ tree.update(index, 0);
208+ ans = max(ans, tree.getMaxSubarraySum());
209+ for (const int index : indices)
210+ tree.update(index, num);
211+ }
212+
213+ return ans;
214+ }
215+ };
106216```
107217
108218#### Go
109219
110220``` go
221+ func maxSubarraySum (nums []int ) int64 {
222+ ans := int64 (nums[0 ])
223+ prefix := int64 (0 )
224+ minPrefix := int64 (0 )
225+
226+ modifiedMinPrefix := int64 (0 )
227+ count := make (map [int ]int64 )
228+ minPrefixPlusRemoval := make (map [int ]int64 )
229+
230+ for _ , num := range nums {
231+ n64 := int64 (num)
232+ prefix += n64
233+ if prefix-modifiedMinPrefix > ans {
234+ ans = prefix - modifiedMinPrefix
235+ }
236+ if n64 < 0 {
237+ count[num]++
238+ prev := minPrefixPlusRemoval[num] // по умолчанию 0
239+ minPrefixPlusRemoval[num] = min (prev, minPrefix) + n64
240+ modifiedMinPrefix = min (modifiedMinPrefix, count[num]*n64)
241+ modifiedMinPrefix = min (modifiedMinPrefix, minPrefixPlusRemoval[num])
242+ }
243+ minPrefix = min (minPrefix, prefix)
244+ modifiedMinPrefix = min (modifiedMinPrefix, minPrefix)
245+ }
246+
247+ return ans
248+ }
249+
250+ func min (a , b int64 ) int64 {
251+ if a < b {
252+ return a
253+ }
254+ return b
255+ }
256+ ```
257+
258+ #### Rust
259+
260+ ``` rust
261+ use std :: collections :: HashMap ;
262+
263+ impl Solution {
264+ pub fn max_subarray_sum (nums : Vec <i32 >) -> i64 {
265+ let mut ans : i64 = * nums . iter (). max (). unwrap () as i64 ;
266+ let mut prefix : i64 = 0 ;
267+ let mut min_prefix : i64 = 0 ;
268+
269+ let mut modified_min_prefix : i64 = 0 ;
270+ let mut count : HashMap <i32 , i64 > = HashMap :: new ();
271+ let mut min_prefix_plus_removal : HashMap <i32 , i64 > = HashMap :: new ();
272+
273+ for & num in nums . iter () {
274+ let n64 = num as i64 ;
275+ prefix += n64 ;
276+ ans = ans . max (prefix - modified_min_prefix );
277+
278+ if n64 < 0 {
279+ let entry = count . entry (num ). or_insert (0 );
280+ * entry += 1 ;
281+
282+ let prev = * min_prefix_plus_removal . get (& num ). unwrap_or (& 0 );
283+ min_prefix_plus_removal . insert (num , prev . min (min_prefix ) + n64 );
284+
285+ modified_min_prefix = modified_min_prefix . min (* entry * n64 );
286+ modified_min_prefix = modified_min_prefix . min (* min_prefix_plus_removal . get (& num ). unwrap ());
287+ }
288+
289+ min_prefix = min_prefix . min (prefix );
290+ modified_min_prefix = modified_min_prefix . min (min_prefix );
291+ }
111292
293+ ans
294+ }
295+ }
112296```
113297
114298<!-- tabs:end -->
0 commit comments