Problem Description: for an array with positive and negative, find the maximum value of its continuous subsequence
Solution 1: exhaustive violence
Enumerate the left endpoint and the right endpoint, then traverse and update all the subsequence sums, and the final result is the largest
#include<bits/stdc++.h> using namespace std; const int N = 1e5+10; int a[N],b[N]; int n ; int ans ; const int INF = 0x3f3f3f; int main() { int n; cout<<"please input size"<<endl; cin>>n; cout<<"please input data"<<endl; for(int i =1;i<=n;++i) { cin>>a[i]; } int ans = -INF; for(int i =1;i<=n;++i) { for(int j =i;j<=n;++j) { int sum = 0; for(int k=i;k<=j;++k) { sum+=a[k]; } ans = max(ans,sum); } } cout<<ans<<endl; return 0; }
Solution 2: monotone queue solution
Idea: maintain a monotonically increasing prefix and queue. The queue head element is the minimum value of the whole sequence. While maintaining the queue, subtract the minimum value from the prefix and element to get the maximum value, which is the maximum value of the array's subsequence
#include<bits/stdc++.h> using namespace std; const int N = 1e5+10; int a[N],b[N]; int n ; int ans ; const int INF = 0x3f3f3f; deque<int> q; int main() { int n; cout<<"please input size"<<endl; cin>>n; cout<<"please input data"<<endl; for(int i =1;i<=n;++i) { cin>>a[i]; } q.push_back(0),b[0] = 0; for(int i =1;i<=n;++i) { b[i] = b[i-1]+a[i]; ans = max(ans,b[i]-b[q.front()]); while(!q.empty()&&b[i]<=b[q.back()]) q.pop_back(); q.push_back(i); } cout<<ans<<endl; return 0; }
Solution 3: divide and conquer
Thinking: discussion in three situations
1. Calculate the sum of the sum of left to k, and record it as left sum;
2. Calculate the sum of k+1 to right, and record it as "right" sum;
3. Cross boundary sum, and sum to both sides with k as the center
1. Expand one step from the center to the left, record the current sum1, and compare it with the previous step. If it is greater than, update the left
2. Expand one step from the center to the right, record the current sum2, and compare it with the previous step. If it is greater than, update the right
3. Calculate continuous fields and sum = sum1+sum2;
After calculation, take the maximum of three
#include<bits/stdc++.h> using namespace std; const int N = 1e5+10; int a[N],b[N], dp[N];; int n ; int ans ; const int INF = 0x3f3f3f; int solve4(int l,int r) { if(l==r) return a[l]; int mid = (l+r)>>1; int left_sum = solve4(l,mid); int right_sum = solve4(mid+1,r); int sum1=0,sum2=0,s1=0,s2=0; //In the case of a key pull-up, there is a pull-up? for(int i =mid;i>=l;--i) { s1+=a[i]; sum1=max(sum1,s1); } for(int i =mid+1;i<=r;++i) { s2 +=a[i]; sum2 = max(sum2,s2); } int sum = sum1+sum2; return max(max(left_sum,right_sum),sum); } int main() { int n; cout<<"please input size"<<endl; cin>>n; cout<<"please input data"<<endl; for(int i =1;i<=n;++i) { cin>>a[i]; } int ans = solve4(1,n); cout<<ans<<endl; system("pause"); return 0; }
4. Dynamic planning
Train of thought: This is the simplest problem that can be considered with the idea of dynamic planning. The decision at each step is nothing more than whether to continue to add the next element to the current sub segment
Dynamic planning shows great skill. Let's open an array dp [] to record the sum of the largest one of all the sub segments ending with a[i] represented by dp[i]. In this way, we can consider whether to add the next element to the current sub segment according to the positive and negative dp[i]. If dp[i] is negative, why don't we maintain a new sub segment from a[i+1]? If dp[i] is a positive number, then obviously you can continue to add a[i+1] to the current sub segment.
Finally, we just need to find out the biggest one of all the largest sub segments.
#include<bits/stdc++.h> using namespace std; const int N = 1e5+10; int a[N],b[N], dp[N];; int n ; int ans ; const int INF = 0x3f3f3f; int main() { int n; cout<<"please input size"<<endl; cin>>n; cout<<"please input data"<<endl; for(int i =1;i<=n;++i) { cin>>a[i]; } dp[1] = a[1]; int ans =0; for(int i =2;i<=n;++i) { if(dp[i-1]>0) dp[i] =dp[i-1] + a[i]; else dp[i] = a[i]; ans = max(ans,dp[i]); } cout<<ans<<endl; system("pause"); return 0; }