首页 > 其他 > 详细

洛谷 SP1043 GSS1

时间:2020-01-17 17:08:17      阅读:83      评论:0      收藏:0      [点我收藏+]

题目链接

我们考虑线段树维护信息

首先任意一个子段都可以划分为若干区间

也就是一个区间内的最大子段和,必然等于某些连续小区间的区间和之和

维护四个值

  1. 区间最大子段和

  2. 区间和

  3. 区间最大前缀和

  4. 区间最大后缀和

显然区间和直接维护,区间最大前缀和就是 左区间前缀 或 右区间前缀加左区间区间和 的最大值,后缀同理

区间子段和就是左右区间的子段和的最大值,与左区间后缀加右区间前缀之和比大小,

以上解决

[code]

#include <bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define ls (nod<<1)
#define rs (nod<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r

const int N=5e4+50;

int read(){
    int x=0,flag=1; char c;
    for(c=getchar();!isdigit(c);c=getchar()) if(c=='-') flag=-1;
    for(;isdigit(c);c=getchar()) x=((x+(x<<2))<<1)+(c^48); 
    return x*flag;
}

int n;

struct Node{
    int l,r;
    int lv,rv,v;
    int sum;
}t[N<<2];

Node Union(Node x,Node y){
    Node z;
    z.l=x.l; z.r=y.r;
    z.sum=x.sum+y.sum;
    z.lv=max(x.lv,x.sum+y.lv);
    z.rv=max(y.rv,y.sum+x.rv);
    z.v=max(max(x.v,y.v),x.rv+y.lv);
    return z;
}

void pushup(int nod){
    if(t[nod].l==t[nod].r) return ;
    t[nod]=Union(t[ls],t[rs]);
}

void build(int nod,int l,int r){
    t[nod].l=l,t[nod].r=r;
    if(l==r){
        t[nod].sum=t[nod].lv=t[nod].rv=t[nod].v=read();
        return ;
    }
    build(lson),build(rson);
    pushup(nod);
}

Node query(int nod,int l,int r,int ll,int rr){
    if(l==ll&&r==rr) return t[nod];
    if(rr<=mid) return query(lson,ll,rr);
    else if(ll>mid) return query(rson,ll,rr);               
    else return Union(query(lson,ll,mid),query(rson,mid+1,rr));
}

int main() {
    n=read();
    build(1,1,n);
    int m=read();
    while(m--){
        int l=read(),r=read();
        printf("%d\n",query(1,1,n,l,r).v);
    }
    return 0;
}

洛谷 SP1043 GSS1

原文:https://www.cnblogs.com/zzhzzh123/p/12206574.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!