Classic problem
Given a sequence comprising positive and negative values, and obtains the maximum continuous subsequence
Solution: Maintain two end positions first, end had appeared with the previous maximum and sum, the current and s.
See in particular the code
#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
int dp[maxn];
int main(){
int n,i,j;
int sum,s;
int first,end,t;//最大连续子串和的起始及末尾
while(scanf("%d",&n)&&(n!=0)){
for(i=0;i<n;i++)
cin>>dp[i];
sum=dp[0];s=0;first=end=t=0;
for(i=0;i<n;i++){
s+=dp[i];
if(s>sum){
sum=s;
first=t;
end=i;
}
if(s<=0){
s=0;
t=i+1;
}
}
if(sum<=0) cout<<dp[0]<<" "<<dp[n-1]<<endl;
else cout<<sum<<" "<<dp[first]<<" "<<dp[end]<<endl;
}
return 0;
}
Advanced issues --GSS
Given a sequence of interrogation with m, both inclusive given each interrogation, the maximum value of the Q most contiguous subsequence therebetween, while the need to modify the supporting elements
Then the previous question, we use the linear solution method, the time complexity is only O (n), but we have another way to solve the above problem, that is, divide and conquer
We know that the maximum continuous section of a subsequence is obtained by left and right parts, the need to maintain the value of three sub-segments of the left and right at the time of maintenance of the sub-sections A, B, namely the maximum value Maxx contiguous subsequence, from the sequence of the left end of the maximum value lmax, from the right end of the maximum value rmax
To do this time complexity of O (nlogn)
So the largest sub-segment interval and for the
max(max(A.maxx,B.maxx),A.rmax+B.lmax)
Wherein the left end of the sub-sequences for the A, B for the right sub-sequence segment
So when we have multiple queries can use segment tree, each node in the tree line maintenance of six values (l, r, lmax, rmax, maxx, sum
See push_up function merge operations
//带单点修改,详见push_up和update函数
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
int A[N];
struct seg_tree{
struct node{
int l,r;
int lmax;
int rmax;
int maxx;
int sum;
}t[N<<2];
node push_up(node a,node b){
node res;
res.l=a.l;res.r=b.r;
res.lmax=max(a.lmax,a.sum+b.lmax);
res.rmax=max(b.rmax,b.sum+a.rmax);
res.maxx=max(max(a.maxx,b.maxx),a.rmax+b.lmax);
res.sum=a.sum+b.sum;
return res;
}
void build_tree(int l,int r,int rt){
t[rt].l=l;t[rt].r=r;
if(l==r){
t[rt].lmax=t[rt].rmax=t[rt].maxx=t[rt].sum=A[l];
return;
}
int m=(t[rt].l+t[rt].r)>>1;
build_tree(l,m,rt<<1);
build_tree(m,r,rt<<1|1);
t[rt]=push_up(t[rt<<1],t[rt<<1|1]);
}
void update(int idx,int k,int rt){
if(t[rt].r==t[rt].r){
t[rt].lmax=t[rt].maxx=t[rt].rmax=t[rt].sum=k;
return;
}
int mid=(t[rt].l+t[rt].r)>>1;
if(idx<=mid) update(idx,k,rt<<1);
else update(idx,k,rt<<1|1);
t[rt]=push_up(t[rt<<1],t[rt<<1|1]);
}
node query_ans(int l,int r,int rt){
if(l==t[rt].l&&t[rt].r==r){
return t[rt];
}
int m=(t[rt].l+t[rt].r)>>1;
if(r<=m) return query_ans(l,r,rt<<1);
else if(l>m) return query_ans(l,r,rt<<1|1);
else return push_up(query_ans(l,m,rt<<1),query_ans(m+1,r,rt<<1|1));
}
}tree;
int main(){
int n,q,a,b;
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++) cin>>A[i];
tree.build_tree(1,n,1);
cin>>q;
while(q--){
cin>>a>>b;
cout<<tree.query_ans(a,b,1).maxx;
}
}
return 0;
}
GSS1, GSS3, GSS5 same effect
Additional problem:
Each query only needs to be output and the maximum continuous subsequence, but also the output end thereof index of about
Solution: Additional information of four nodes at each node, the right end point Lmax, Rmax of the left point and the left and right end maxx, maintenance the process is carried out in push_up function
Additional problem:
Given a sequence requires two non-adjacent sequences such that non-empty and the maximum
Solution one: obviously be solved with GSS, enumeration discontinuous point (2 ~ n-1), so that the left and right ends of the segment tree asks its most value
Solution two: First, find the largest contiguous subsequence value M of the whole sequence, note the first, the end position, then the query 1 ~ first-1 maximum sequence value L, end + 1 ~ n is the maximum sequence R, first ~ end of the minimum contiguous subsequence X.
Then the final answer is
max(max(M+L,M+R),M-X);