[codevs3981]动态最大子段和不带修改(线段树)

解题关键:最大子段和需要多个信息维护。

注意查询时的pushup。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
#define inf (1<<62)
using namespace std;
typedef long long ll;
const int maxn=200005;
ll a[maxn],sum[maxn<<2],la[maxn<<2],ra[maxn<<2],gss[maxn<<2];
int n;
struct node{
    ll sum,la,ra,gss;
};

void pushup(int rt){
    int l=rt<<1,r=rt<<1|1;
    la[rt]=max(la[l],sum[l]+la[r]);
    ra[rt]=max(ra[r],sum[r]+ra[l]);
    gss[rt]=max(ra[l]+la[r],gss[l]);
    gss[rt]=max(gss[rt],gss[r]);
    sum[rt]=sum[l]+sum[r];
}
void build(int rt,int l,int r){
    if(l==r){
        la[rt]=ra[rt]=gss[rt]=sum[rt]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}


//query有问题,也需要pushup
node query(int rt,int l,int r,int tl,int tr){
    if(tl<=l&&tr>=r){
        return {sum[rt],la[rt],ra[rt],gss[rt]};
    }
    int mid=(l+r)>>1;
    if(tr<=mid) return query(rt<<1, l, mid,tl, tr);
    if(tl>mid) return query(rt<<1|1, mid+1, r,tl, tr);
    node lo=query(rt<<1, l, mid,tl, tr),ro=query(rt<<1|1, mid+1, r,tl, tr),ans;
    ans.sum = lo.sum + ro.sum;
    ans.gss = max(max(lo.gss, ro.gss), lo.ra + ro.la);
    ans.la = max(lo.la, lo.sum + ro.la);
    ans.ra = max(ro.ra, ro.sum + lo.ra);
    return ans;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld",a+i);
    build(1,1,n);
    int q,t1,t2;
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        scanf("%d%d",&t1,&t2);
        ll ans=query(1,1,n,t1,t2).gss;
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2019-02-25 13:45  Elpsywk  阅读(128)  评论(0编辑  收藏  举报