这题可以说是spoj GSSI的拓展题了,它求的是给定区间的最大连续和的两个端点下标。
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4146

#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 500005 struct node{ int l,r,ll,rr; long long lsum,rsum,maxsum; }setree[maxn<<2]; long long sum[maxn]={ 0 }; int ansr,ansl; long long maxsum; void pushup(int rt,int l,int m,int r) { if(setree[rt<<1].lsum>=sum[m]-sum[l-1]+setree[rt<<1|1].lsum){ setree[rt].ll=setree[rt<<1].ll; setree[rt].lsum=setree[rt<<1].lsum; } else{ setree[rt].ll=setree[rt<<1|1].ll; setree[rt].lsum=sum[m]-sum[l-1]+setree[rt<<1|1].lsum; } if(setree[rt<<1|1].rsum>sum[r]-sum[m]+setree[rt<<1].rsum){ setree[rt].rr=setree[rt<<1|1].rr; setree[rt].rsum=setree[rt<<1|1].rsum; } else{ setree[rt].rr=setree[rt<<1].rr; setree[rt].rsum=sum[r]-sum[m]+setree[rt<<1].rsum; } if(setree[rt<<1].maxsum>=setree[rt<<1|1].maxsum){ setree[rt].maxsum=setree[rt<<1].maxsum; setree[rt].l=setree[rt<<1].l; setree[rt].r=setree[rt<<1].r; } else{ setree[rt].maxsum=setree[rt<<1|1].maxsum; setree[rt].l=setree[rt<<1|1].l; setree[rt].r=setree[rt<<1|1].r; } if(setree[rt].maxsum<setree[rt<<1].rsum+setree[rt<<1|1].lsum){ setree[rt].l=setree[rt<<1].rr; setree[rt].r=setree[rt<<1|1].ll; setree[rt].maxsum=setree[rt<<1].rsum+setree[rt<<1|1].lsum; } else if(setree[rt].maxsum==setree[rt<<1].rsum+setree[rt<<1|1].lsum){ if(setree[rt].l>setree[rt<<1].rr){ setree[rt].l=setree[rt<<1].rr; setree[rt].r=setree[rt<<1|1].ll; } else if(setree[rt].l==setree[rt<<1].rr) setree[rt].r=min(setree[rt].r,setree[rt<<1|1].ll); } } void build(int l,int r,int rt) { if(l==r){ setree[rt].l=setree[rt].r=r; setree[rt].ll=setree[rt].rr=r; scanf("%lld",&setree[rt].maxsum); setree[rt].lsum=setree[rt].rsum=setree[rt].maxsum; sum[l]=sum[l-1]+setree[rt].lsum; return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt,l,m,r); } long long queryr(int l,int r,int rt,int L,int R) { if(L==l&&r==R){ ansl=setree[rt].rr; return setree[rt].rsum; } int m=(l+r)>>1; if(R<=m) return queryr(lson,L,R); else if(L>m) return queryr(rson,L,R); else{ long long res1=queryr(rson,m+1,R); int tmp=ansl; long long res2=sum[R]-sum[m]+queryr(lson,L,m); if(res2<res1){ ansl=tmp; return res1; } return res2; } } long long queryl(int l,int r,int rt,int L,int R) { if(L==l&&r==R){ ansr=setree[rt].ll; return setree[rt].lsum; } int m=(l+r)>>1; if(R<=m) return queryl(lson,L,R); else if(L>m) return queryl(rson,L,R); else{ long long res1=queryl(lson,L,m); int tmp=ansr; long long res2=sum[m]-sum[L-1]+queryl(rson,m+1,R); if(res1>=res2){ ansr=tmp; return res1; } return res2; } } long long query(int l,int r,int rt,int L,int R) { if(L==l&&r==R){ if(maxsum<setree[rt].maxsum){ maxsum=setree[rt].maxsum; ansl=setree[rt].l; ansr=setree[rt].r; } return setree[rt].maxsum; } int m=(l+r)>>1; if(R<=m) return query(lson,L,R); else if(L>m) return query(rson,L,R); else{ long long ans1=query(lson,L,m); long long ans2=query(rson,m+1,R); int tmpl=ansl,tmpr=ansr; long long rsum=queryr(lson,L,m); long long lsum=queryl(rson,m+1,R); if(maxsum>lsum+rsum){ ansl=tmpl; ansr=tmpr; return max(ans1,ans2); } else if(maxsum==lsum+rsum){ if(tmpl<ansl){ ansl=tmpl; ansr=tmpr; } else if(tmpl==ansl); ansr=min(ansr,tmpr); return max(ans1,ans2); } else{ maxsum=lsum+rsum; return lsum+rsum; } } } int main() { int n,m,cas=1; while(~scanf("%d%d",&n,&m)){ build(1,n,1); printf("Case %d:\n",cas++); while(m--){ int l,r; maxsum=-(long long)1e15; scanf("%d%d",&l,&r); query(1,n,1,l,r); printf("%d %d\n",ansl,ansr); } } return 0; }