题意描述:给出一个长度为n的证书序列D,你的任务是对m个询问做出回答。对于询问(a,b),需要找到两个下标x和y,使得a<=x<=y<=b,并且Dx+...Dy尽量大。如果有多组满足,x应尽量小。如果还有多解,y应尽量小。
==没有力气写题解了,Wa了五次,累觉不爱,记录一下五次分别改的地方好了。Time排进了前十。。还是比较开心。。
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=500000+10;
struct node{
int l,r;
long long sum,pre,suf,ma;
int R,L;
}o[maxn*4];
long long a[maxn];
void build(int e,int x,int y){
if(x==y){o[e].sum=o[e].pre=o[e].suf=o[e].ma=a[x];
o[e].l=o[e].r=o[e].R=o[e].L=x;
return;
}
else{
int mid=x+(y-x)/2;
build(e*2,x,mid);
build(e*2+1,mid+1,y);
o[e].sum=o[e*2].sum+o[e*2+1].sum;
int luck=1;
long long now=o[e*2].ma;<span style="color:#ff0000;">//第五次 ans定义成了int</span>
if(now<(o[e*2].suf+o[e*2+1].pre)){luck=3;now=o[e*2].suf+o[e*2+1].pre;}//<span style="color:#ff0000;">第二次 判断条件都写对了 后面写成了</span><span style="color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif;">now=o[e*2].suf+o[e*2+1].sum;</span><span style="color:#ff0000;">
</span> //<span style="color:#ff0000;">第三次 这两行换了位置,导致0 0 3 询问1 3 时 答案是3 3</span>
if(now<o[e*2+1].ma){luck=2;now=o[e*2+1].ma;}
o[e].ma=now;
if(luck==1){
o[e].l=o[e*2].l;
o[e].r=o[e*2].r;
}
if(luck==2){
o[e].l=o[e*2+1].l;
o[e].r=o[e*2+1].r;
}
if(luck==3){
o[e].l=o[e*2].L;
o[e].r=o[e*2+1].R;
}
if(o[e*2].pre>=o[e*2].sum+o[e*2+1].pre){
o[e].pre=o[e*2].pre;
o[e].R=o[e*2].R;
}
else {o[e].pre=o[e*2].sum+o[e*2+1].pre;
o[e].R=o[e*2+1].R;
}
if((o[e*2].suf+o[e*2+1].sum)>=o[e*2+1].suf){
o[e].suf=o[e*2].suf+o[e*2+1].sum;
o[e].L=o[e*2].L;
}
else{
o[e].suf=o[e*2+1].suf;
o[e].L=o[e*2+1].L;
}
}
}
node query(int left,int right,int e,int x,int y){
if(left<=x&&right>=y){return o[e];}
else{
int mid=x+(y-x)/2;//<span style="color:#ff0000;">第一次 写成了mid=x+(y-x);</span>
if(right<=mid) return query(left,right,e*2,x,mid);
if(left>mid)return query(left,right,e*2+1,mid+1,y);
node first,second,ans;
first=query(left,mid,e*2,x,mid);
second=query(mid+1,right,e*2+1,mid+1,y);
ans.sum=first.sum+second.sum;
int luck=1;
ans.ma=first.ma;
if(ans.ma<first.suf+second.pre){ luck=3;ans.ma=first.suf+second.pre;}//<span style="color:#ff0000;">第四次 第三次换的时候看走眼了 把下面的换了 这一处没换 </span>
if(ans.ma<second.ma){ luck=2;ans.ma=second.ma;}
if(luck==1){ ans.l=first.l;ans.r=first.r;}
if(luck==3){ ans.l=first.L;ans.r=second.R;}
if(luck==2){ ans.l=second.l;ans.r=second.r;}
if(first.pre>=(first.sum+second.pre)){ans.pre=first.pre;ans.R=first.R; }
else {ans.pre=first.sum+second.pre;ans.R=second.R;}
if((first.suf+second.sum)>=second.suf){ans.suf=first.suf+second.sum;ans.L=first.L;}
else {ans.suf=second.suf;ans.L=second.L;}
return ans;
}
}
int main(){
int n,m;
int T=1;
while(scanf("%d%d",&n,&m)!=EOF){
// init();
for(int i=1;i<=n;i++) {
scanf("%lld",&a[i]);
}
build(1,1,n);
printf("Case %d:\n",T++);
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
node ans;
ans=query(x,y,1,1,n);
printf("%d %d\n",ans.l,ans.r);
}
}
return 0;
}