洛谷 SP1043 GSS1
我们考虑线段树维护信息
首先任意一个子段都可以划分为若干区间
也就是一个区间内的最大子段和,必然等于某些连续小区间的区间和之和
维护四个值
-
区间最大子段和
-
区间和
-
区间最大前缀和
-
区间最大后缀和
显然区间和直接维护,区间最大前缀和就是 左区间前缀 或 右区间前缀加左区间区间和 的最大值,后缀同理
区间子段和就是左右区间的子段和的最大值,与左区间后缀加右区间前缀之和比大小,
以上解决
[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;
}