题目:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4146
经典线段树。。真的很经典的一个题。但是我断断续续写了接近两天才AC。主要是找BUG。。很多东西没有考虑完全,就开始写了。
在那个没有思考完全的代码下修改,太蛋碎了。
主要存放 3个东西,一个最长前缀。pre_max, 区间连续的最大和,all_max,还有存放后缀 suf_max;
一段区间的all_max可能由以下5个组成。
1 左区间的 all_max;
2 右区间的all_max;
3 左边的sum+右区间的pre_max;
4 右边的sum+左边的suf_max;
5 左边的suf_max+右边的pre_max;
把这个主体想清楚。其他的差不多。然后要注意边界。
#include <cmath> #include <ctime> #include <iostream> #include <string> #include <vector> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <map> #include <set> #include <algorithm> #include <cctype> #include <stack> #include <deque> using namespace std; typedef long long LL; #define eps 10e-9 #define inf 0x3f3f3f3f const int maxn = 500000+100; LL a[maxn]; struct node{ int l,r; int pr,sl; LL sum,pre_max,all_max,suf_max; }ans[maxn<<2]; void pushup(int id,int l,int r){ int m=(l+r)>>1; ans[id].sum=ans[id<<1].sum+ans[id<<1|1].sum; ans[id].pre_max=ans[id<<1].pre_max; ans[id].pr=ans[id<<1].pr; ans[id].suf_max=ans[id<<1|1].suf_max; ans[id].sl=ans[id<<1|1].sl; ans[id].all_max=ans[id<<1].sum+ans[id<<1|1].pre_max; ans[id].l=l; ans[id].r=ans[id<<1|1].pr; if(ans[id].all_max<ans[id<<1].all_max||( ans[id].all_max==ans[id<<1].all_max&&(ans[id].l==ans[id<<1].l) )){ ans[id].all_max=ans[id<<1].all_max; ans[id].l=ans[id<<1].l; ans[id].r=ans[id<<1].r; } if(ans[id<<1].suf_max+ans[id<<1|1].pre_max>ans[id].all_max|| (ans[id<<1].suf_max+ans[id<<1|1].pre_max==ans[id].all_max&&ans[id<<1].sl<ans[id].l)){ ans[id].all_max=ans[id<<1].suf_max+ans[id<<1|1].pre_max; ans[id].l=ans[id<<1].sl; ans[id].r=ans[id<<1|1].pr; } if(ans[id].all_max<ans[id<<1|1].sum+ans[id<<1].suf_max|| (ans[id].all_max==ans[id<<1|1].sum+ans[id<<1].suf_max&&ans[id<<1].sl<ans[id].l)){ ans[id].all_max=ans[id<<1|1].sum+ans[id<<1].suf_max; ans[id].l=ans[id<<1].sl; ans[id].r=r; } if(ans[id].all_max<ans[id<<1|1].all_max|| ans[id].all_max==ans[id<<1|1].all_max&&ans[id].l>ans[id<<1].sl ){ ans[id].all_max=ans[id<<1|1].all_max; ans[id].l=ans[id<<1|1].l; ans[id].r=ans[id<<1|1].r; } if(ans[id<<1].sum+ans[id<<1|1].pre_max>ans[id].pre_max){ ans[id].pre_max=ans[id<<1].sum+ans[id<<1|1].pre_max; ans[id].pr=ans[id<<1|1].pr; } if(ans[id<<1|1].sum+ans[id<<1].suf_max>=ans[id].suf_max){ ans[id].suf_max=ans[id<<1|1].sum+ans[id<<1].suf_max; ans[id].sl=ans[id<<1].sl; } } void build(int id,int l,int r){ if(l==r){ ans[id].sum=ans[id].pre_max=ans[id].all_max=ans[id].suf_max=a[l]; ans[id].l = ans[id].r= ans[id].pr=ans[id].sl=l; return ; } int m=(l+r)>>1; build(id<<1,l,m); build(id<<1|1,m+1,r); pushup(id,l,r); } node query(int id,int l,int r,int L,int R){ if(l==L&&r==R){ return ans[id]; } int m=(L+R)>>1; if(r<=m) return query(id<<1,l,r,L,m); else if(l>m) return query(id<<1|1,l,r,m+1,R); else{ node t1=query(id<<1,l,m,L,m); node t2=query(id<<1|1,m+1,r,m+1,R); node t=t1; t.sl=t2.sl; t.suf_max=t2.suf_max; t.sum=t1.sum+t2.sum; t.all_max=t1.sum+t2.pre_max; t.l=l; t.r=t2.pr; if(t.all_max<t1.all_max||(t.all_max==t1.all_max&&t.l==t1.l) ){ t.all_max=t1.all_max; t.l=t1.l; t.r=t1.r; } if(t1.suf_max+t2.pre_max>t.all_max|| (t1.suf_max+t2.pre_max==t.all_max&&t1.sl<t.l)){ t.all_max=t1.suf_max+t2.pre_max; t.l=t1.sl; t.r=t2.pr; } if(t2.sum+t1.suf_max>t.all_max|| (t2.sum+t1.suf_max==t.all_max&&t1.sl<t.l)){ t.all_max=t1.suf_max+t2.sum; t.l=t1.sl; t.r=r; } if(t2.all_max>t.all_max){ t.all_max=t2.all_max; t.l=t2.l; t.r=t2.r; } if(t1.sum+t2.pre_max>t.pre_max){ t.pre_max=t1.sum+t2.pre_max; t.pr=t2.pr; } if(t2.sum+t1.suf_max>=t.suf_max){ t.suf_max=t2.sum+t1.suf_max; t.sl=t1.sl; } return t; } } int main(){ int n,m,l,r,ca=1; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=n;i++) scanf("%lld",&a[i]); build(1,1,n); printf("Case %d:\n",ca++); for(int i=0;i<m;i++){ scanf("%d %d",&l,&r); node t=query(1,l,r,1,n); // printf("%d %d %lld %lld %lld\n",t.l,t.r,t.all_max,t.pre_max,t.suf_max); printf("%d %d\n",t.l,t.r); } } return 0; }