题目: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;
}