【题意】
- 给一个n长度的序列,A[1]…A[n],(|A[i]|≤15007,1≤N≤50000)
- M个询问 询问区间内最大连续和
【分析】
*线段树每个节点维护Lmax,Rmax,maxx,sum
- Lmax表示从左端点开始的最大连续和 Rmax同理 maxx不受端点限制 sum
- 表示这节点上的总和
- 转移详见代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50010;
int A[maxn];
struct seg_tree{
struct node{
int l,r,lmax,rmax,maxx,sum;
}Tree[maxn<<2];
node Push_Up(node a,node b){
node res;
res.l=a.l,res.r=b.r;
res.lmax = max(a.lmax,a.sum+b.lmax);
res.rmax = max(b.rmax,b.sum+a.rmax);
res.maxx = max(res.lmax,res.rmax);
res.maxx = max(max(a.maxx,b.maxx),a.rmax+b.lmax);
res.sum=a.sum+b.sum;
return res;
}
void Build(int l,int r,int rt){
Tree[rt].l=l,Tree[rt].r=r;
if(l==r){
Tree[rt].lmax=Tree[rt].rmax=Tree[rt].maxx=Tree[rt].sum=A[l];
return ;
}
int m = (Tree[rt].l+Tree[rt].r)>>1;
Build(l,m,rt<<1);
Build(m+1,r,rt<<1|1);
Tree[rt]=Push_Up(Tree[rt<<1],Tree[rt<<1|1]);
}
node query_ans(int L,int R,int rt){
if(L==Tree[rt].l&&Tree[rt].r==R){
return Tree[rt];
}
int m = (Tree[rt].l+Tree[rt].r)>>1;
if(R<=m) return query_ans(L,R,rt<<1);
else if(L>m) return query_ans(L,R,rt<<1|1);
else
return Push_Up(query_ans(L,m,rt<<1),query_ans(m+1,R,rt<<1|1));
}
}tree;
int main(){
int n,q,a,b;
while(~scanf("%d",&n)){
for(int i=1; i<=n; i++) scanf("%d",&A[i]);
tree.Build(1,n,1);
scanf("%d",&q);
while(q--){
scanf("%d%d",&a,&b);
printf("%d\n",tree.query_ans(a,b,1).maxx);
}
}
return 0;
}