• codeVS 动态最大子段和


    题目链接:戳我

    对于最大子段和,我们只需要维护四个变量——maxl,maxr,maxs,sum(分别表示区间最大前缀子段和,区间最大后缀子段和,区间最大子段和,区间所有数的和)

    然后合并的时候是这样的:

    t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
    t[x].maxs=max(max(t[ls(x)].maxs,t[rs(x)].maxs),t[ls(x)].maxr+t[rs(x)].maxl);
    t[x].maxl=max(t[ls(x)].maxl,t[ls(x)].sum+t[rs(x)].maxl);
    t[x].maxr=max(t[rs(x)].maxr,t[ls(x)].maxr+t[rs(x)].sum);
    

    然后想要强调的是,询问的时候一定不能像普通线段树那样写,因为我们需要考虑三种情况。一种是该节点表示区间的答案应该从左子节点表示区间取得,一种是该节点表示区间的答案是应该从右子节点表示区间取得,一种是该节点表示区间的答案应该从左右节点中合并取得。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 2000010
    using namespace std;
    int n,m;
    long long a[MAXN];
    struct Node{long long maxs,maxl,maxr,sum;}t[MAXN<<2];
    inline int ls(int x){return x<<1;}
    inline int rs(int x){return x<<1|1;}
    inline void push_up(int x)
    {
    	t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
    	t[x].maxs=max(max(t[ls(x)].maxs,t[rs(x)].maxs),t[ls(x)].maxr+t[rs(x)].maxl);
    	t[x].maxl=max(t[ls(x)].maxl,t[ls(x)].sum+t[rs(x)].maxl);
    	t[x].maxr=max(t[rs(x)].maxr,t[ls(x)].maxr+t[rs(x)].sum);
    }
    inline void build(int x,int l,int r)
    {
    	if(l==r) 
    	{
    		t[x].sum=t[x].maxs=t[x].maxl=t[x].maxr=a[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls(x),l,mid);
    	build(rs(x),mid+1,r);
    	push_up(x);
    	//printf("x=%d l=%d r=%d maxs=%d maxl=%d maxr=%d sum=%d
    ",x,l,r,t[x].maxs,t[x].maxl,t[x].maxr,t[x].sum);
    }
    inline Node query(int x,int l,int r,int ll,int rr)
    {
    	//printf("x=%d l=%d r=%d ll=%d rr=%d
    ",x,l,r,ll,rr);
    	if(ll==l&&r==rr) {return t[x];}
    	int mid=(l+r)>>1;
    	if(rr<=mid) return query(ls(x),l,mid,ll,rr);
    	else if(mid<ll) return query(rs(x),mid+1,r,ll,rr);
    	else
    	{
    		Node lson=query(ls(x),l,mid,ll,mid),rson=query(rs(x),mid+1,r,mid+1,rr),ans;
    		ans.sum=lson.sum+rson.sum;
    		ans.maxs=max(max(lson.maxs,rson.maxs),lson.maxr+rson.maxl);
    		ans.maxl=max(lson.maxl,lson.sum+rson.maxl);
    		ans.maxr=max(rson.maxr,lson.maxr+rson.sum);
    		return ans;
    	}
    }
    
    int main()
    {
    	freopen("ce1.in","r",stdin);
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	build(1,1,n);
    	scanf("%d",&m);
    	for(int i=1;i<=m;i++)
    	{
    		long long l,r;
    		scanf("%lld%lld",&l,&r);
    		printf("%lld
    ",query(1,1,n,l,r).maxs);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Fiddler 简介
    jQuery 属性操作
    Win7的虚拟Wi-Fi
    接口与内部类
    继承(二)
    J2EE框架(Struts&Hibernate&Spring)的理解
    继承(一)
    对象与类
    控制流程
    数据类型
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10389194.html
Copyright © 2020-2023  润新知