Maximum continuous sub-segments and issues

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);

Guess you like

Origin blog.csdn.net/qq_41860129/article/details/91848526