# Maximum sub segment sum

Keywords: Dynamic Programming partitioning

# Maximum sub segment sum

Problem: given the sequence a[1],a[2],a[3],..., a[n] composed of N integers (possibly negative numbers), find the maximum value of the sum of sub segments of the sequence such as a[i]+a[i+1] +... + a[j]. When all the given integers are negative, the sub segment sum is defined as 0. According to this definition, the optimal value is: Max{0,a[i]+a[i+1] +... + a[j]}, 1 < = I < = J < = n. for example, when a[]=(-20,11,-4,13,-5,-2), the maximum sub segment sum is 20.

The above content comes from Baidu Encyclopedia

# Thought 1: recursive thought

Analyzing this problem, we can think of it as follows:
Let's make a middle line of the given array, set it as mid, and then divide it into two parts. How many situations are there that may occur for the maximum sub segment sum?

1. It appears in the left part, that is, the maximum sub segment sum on the left is greater than that on the right
2. It appears in the right part, opposite to the above
3. It appears in the middle, that is, the center line is clamped in the middle

Then, with the idea of dichotomy, can we also perform the above steps on the left until there is only one element, that is, to the point of base case? At this time, I will return this value and go to the right. When both sides are finished, I'll look at the situation in the middle, and then find the larger of the three and return to the next level.

Let me talk more about how to deal with the intermediate situation:

Since the largest sub segment and appear in the middle, does it mean that some data appear on the left of the midline and some data appear on the right of the midline? Then, I calculate the maximum of the sum of the numbers with the center line to the left and the maximum of the sum of the numbers with the center line to the right, and finally add them together. Is it the maximum sub segment sum in my middle?

OK, let's look at the code below:

## code

int max_sub_sum(int arr[], int l, int r) {
if (l == r)
return max(arr[l], 0);
else {
int mid = l + (r - l) / 2;
int lres = max_sub_sum(arr, l, mid);      //Find the largest sub segment on the left and
int rres = max_sub_sum(arr, mid + 1, r);  //Find the largest sub segment and on the right
int lmax = 0, rmax = 0, sum = 0;
for (int i = mid; i >= l; i--) {          //Find the sum and maximum of the number to the left of the center line
sum += arr[i];
lmax = max(sum, lmax);
}
sum = 0;
for (int i = mid + 1; i <= r; i++) {      //Sum and maximum of the number to the right of the centerline
sum += arr[i];
rmax = max(sum, rmax);
}
int midres = lmax + rmax;                 //The sum of the two sides is the maximum sub segment sum in the middle case
return max(max(lres, rres), midres);
}
}


## Time complexity analysis

$$T(n)=2T(\frac{n}{2})+2O(n)+O(1)$$

According to the master formula, \ (a=2,b=2,d=1\to\log_ba=1=d \), then the time complexity:

$T(n)=O(n*log{n})$

If you don't know the time complexity of the master, you can check it in this blog post

# Idea 2: dynamic programming (supplementary)

After learning dynamic programming, the teacher still assigned us this problem, but it is called the maximum sub sequence and problem. At first, I thought it was something. Later, I found that it is still the maximum sub segment and problem, but now it is done in a different way, that is, dynamic programming.

When we look at the divide and conquer method, we can find that when it solves the largest sub segment and problem in the middle part, it still uses the enumeration method, that is, it still repeats the previous traversal. Then we can think of a method. How can we make the greatest use of the data I have passed in front for later decisions?

Let's rethink this problem. Is our problem equivalent to finding the maximum suborder sum of a sequence of length n?

Let's split this problem, or turn it into a more general problem:

We find the maximum suborder sum of length i, or the maximum suborder sum of the first i numbers of a known sequence.

Let's think like this. Can we make a decision by using the maximum suborder sum of the first i-1 length sequence and the value a[i] at the current position to find the maximum suborder sum of length I? Let d[i] represent the maximum suborder sum of the sequence of the first I lengths. Then, as mentioned above, when finding d[i], we can use d[i-1] to make decisions. Then d[i] has the following two cases:

d[i]=d[i-1]+a[i] ,d[i-1]<0
d[i]=a[i]        ,d[i-1]>=0


This is also easy to understand. If the previous maximum suborder sum is negative, then \ (d [I-1] + a[i] < a[i] \), I might as well take a[i] as my current maximum suborder sum! After understanding, the code is also very simple.

## Dynamic programming code

/* Maximum subsequence (segment) sum */
#include <iostream>
using namespace std;
const int N=1e5+10;
int arr[N],d[N],n;
int main(){
cin >> n;
for(int i=1;i<=n;i++){
cin >> arr[i];
}
for(int i=1;i<=n;i++){
if(d[i-1]<=0){
d[i]=arr[i];
}
else{
d[i]=d[i-1]+arr[i];
}
}
int maxn=0;
for(int i=0;i<=n;i++){
maxn=max(maxn,d[i]);
}
cout << maxn;
return 0;
}


Time complexity: \ (O(n) \)

## improvement

The above content has a major premise, that is, the given array cannot be all negative numbers, but after brushing the question, I found that this is not in other people's requirements. Therefore, it should be improved. For all arrays, a maximum sub order sum can be returned.

/* Maximum subsequence (segment) sum */
#include <iostream>
using namespace std;
const int N=1e6+10;
int arr[N],n;
int main(){
cin >> n;
for(int i=0;i<n;i++){
cin >> arr[i];
}
int pre=arr[0];
int maxn=arr[0];
for(int i=1;i<n;i++){
pre=max(pre+arr[i],arr[i]);
maxn=max(maxn,pre);
}
cout << maxn;
return 0;
}


# subject

Los Angeles Valley: https://www.luogu.com.cn/problem/P1115

Posted by spiffy577 on Tue, 09 Nov 2021 01:54:08 -0800