动态最大连续和

来源:互联网 发布:apache hadoop 安装 编辑:程序博客网 时间:2024/06/06 03:43

题目描述:略

题目分析:
关键字:SegmentTree(线段树)
裸的数据结构题,直接给你操作,让你用数据结构维护之前的操作从而降低复杂度,加快查询,加快修改,这里用的是线段树维护。

小细节:
比如题中的最大连续和,怎么通过两段求出最大连续和呢?自己脑补一下,最大的连续和要么在左边一段中,要么在右边一段中,要么贯穿两个序列,有一段在左边,一段在右边,这时我们就在tree中加入Lsum和Rsum(分别为从右(左)端开始的最大连续和),并进行维护,又同时的怎么通过两端维护Lsum呢,其实也很简单,要么是左边一段的Lsum,要么贯穿左边的一段,加上右边的最大连续和,那么再维护一个tot(序列的总值就可以了)。(具体看代码):

#include<cstdio>#define M 100005#define Psaily authorusing namespace std;int n,m,flag,a,b;int A[M];inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a>b?b:a;}inline void chkmax(int &a,int b){if(a<b)a=b;}inline void chkmin(int &a,int b){if(a>b)a=b;}inline void chkmin(int &a,int b,int c){if(a>min(b,c))a=min(b,c);}inline void chkmax(int &a,int b,int c){if(a<max(b,c))a=max(b,c);}struct SegmentTree{    struct node{        int L,R,Lsum,Rsum,Asum,tot;    }tree[M<<2];    inline void Up(node &p,node a,node b){        p.tot=a.tot+b.tot;        p.Asum=max(a.Asum,b.Asum);        chkmax(p.Asum,a.tot+b.Lsum,b.tot+a.Rsum);        chkmax(p.Asum,a.Rsum+b.Lsum);        p.Lsum=a.Lsum;chkmax(p.Lsum,a.tot+b.Lsum);        p.Rsum=b.Rsum;chkmax(p.Rsum,b.tot+a.Rsum);    }    void build(int L=1,int R=n,int p=1){        tree[p].L=L,tree[p].R=R;        if(L==R){            tree[p].tot=tree[p].Asum=tree[p].Lsum=tree[p].Rsum=A[L];            return;        }        int mid=(L+R)>>1;        build(L,mid,p<<1);        build(mid+1,R,p<<1|1);        Up(tree[p],tree[p<<1],tree[p<<1|1]);    }    node query(int L,int R,int p=1){        if(tree[p].L==L&&tree[p].R==R)return tree[p];        node res;        int mid=(tree[p].L+tree[p].R)>>1;        if(mid>=R) res=query(L,R,p<<1);        else if(mid<L) res=query(L,R,p<<1|1);        else Up(res,query(L,mid,p<<1),query(mid+1,R,p<<1|1));        return res;    }    void update(int pos,int x,int p=1){        if(tree[p].L==tree[p].R){            tree[p].tot=tree[p].Asum=tree[p].Lsum=tree[p].Rsum=x;            return;        }        int mid=(tree[p].L+tree[p].R)>>1;        if(mid>=pos) update(pos,x,p<<1);        else update(pos,x,p<<1|1);        Up(tree[p],tree[p<<1],tree[p<<1|1]);    }}Tree;int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)scanf("%d",&A[i]);    Tree.build();    scanf("%d",&m);    while(m--){        scanf("%d%d%d",&flag,&a,&b);        if(flag)printf("%d\n",Tree.query(a,b).Asum);        else Tree.update(a,b);    }    return 0;}

WA:
1.在Up里,要对合并到的p进行清零,不然可能更新不掉…………
(敲线段树还是需要留点神的)

原创粉丝点击