SPOJ1043 GSS1 (线段树)
Posted modify-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ1043 GSS1 (线段树)相关的知识,希望对你有一定的参考价值。
GSS系列是非常好的线段树、树链剖分练手题目,这道题是最简单的了
题意:求区间最大子段和
显然这道题我们用线段树来解决,难点在于维护最大前缀和以及最大后缀和
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int n,m,cnt,a[5000000]; 5 struct SegmentTree 6 int l,r,pre,suf,data,sum; 7 ; 8 SegmentTree tree[5000000],s; 9 inline void build(int l,int r,int k) 10 tree[k].l=l; 11 tree[k].r=r; 12 if(l==r) 13 tree[k].pre=tree[k].suf=tree[k].data=tree[k].sum=a[l]; 14 return; 15 16 int mid=(l+r)/2; 17 build(l,mid,2*k); 18 build(mid+1,r,2*k+1); 19 tree[k].data=max(tree[2*k].data,tree[2*k+1].data); 20 tree[k].data=max(tree[k].data,tree[2*k].suf+tree[2*k+1].pre); 21 tree[k].pre=max(tree[2*k].pre,tree[2*k].sum+tree[2*k+1].pre); 22 tree[k].suf=max(tree[2*k].suf+tree[2*k+1].sum,tree[2*k+1].suf); 23 tree[k].sum=tree[2*k].sum+tree[2*k+1].sum; //建线段树 24 25 inline void search(int l,int r,int k) 26 if(l<=tree[k].l&&r>=tree[k].r) 27 if(cnt==0) 28 cnt=1; 29 s=tree[k]; 30 else 31 s.pre=max(s.pre,s.sum+tree[k].pre); 32 s.sum=s.sum+tree[k].sum; 33 s.data=max(s.data,tree[k].data); 34 s.data=max(s.data,s.suf+tree[k].pre); 35 s.suf=max(tree[k].suf,s.suf+tree[k].sum); 36 37 return; 38 39 int mid=(tree[k].l+tree[k].r)/2; 40 if(l<=mid) search(l,r,2*k); 41 if(r>mid) search(l,r,2*k+1);//前缀和 42 43 int main() 44 cin>>n; 45 for(int i=1;i<=n;i++) cin>>a[i]; 46 build(1,n,1); 47 int x,y; 48 cin>>m; 49 for(int i=1;i<=m;i++) 50 cin>>x>>y; 51 cnt=0; 52 search(x,y,1); 53 cout<<s.data; 54 putchar(‘\n‘); 55 56 return 0; 57
以上是关于SPOJ1043 GSS1 (线段树)的主要内容,如果未能解决你的问题,请参考以下文章
SP1043 GSS1 - Can you answer these queries I 线段树
SP1043 GSS1 - Can you answer these queries I(线段树,区间最大子段和(静态))
Can you answer these queries I SPOJ - GSS1 (线段树维护区间连续最大值/最大连续子段和)
SP1716 GSS3 - Can you answer these queries III 线段树