uva 1440

题意描述:给出一个长度为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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值