"Ray, Pass me the dishes!"

uvaLive3938:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1939

题意:给你n个数,然后给你一个区间,让你查询这个区间内最大和连续子区间。

题解:哎。智商是硬伤啊,虽然线段树也做过不少题目,但是遇到这样的题目还是不会处理啊,看了别人的代码才明白了怎么做。用那个线段树维护区间最大前缀,最大后缀,以及真正的最大区间。要注意父节点这三个变量是怎么由子节点推导出来的。还是贴代码吧。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N=500009;
  7 int ll[N*3],rr[N*3];
  8 struct  Node{
  9    int pre,suf;
 10    int vx,vy;
 11 }num[N*3];
 12 long long sum[N];
 13 void pushup(int rt,int l,int r){
 14     if(sum[num[rt<<1].pre]-sum[l-1]>=sum[num[rt<<1|1].pre]-sum[l-1])
 15         num[rt].pre=num[rt<<1].pre;
 16     else
 17         num[rt].pre=num[rt<<1|1].pre;
 18     if(sum[r]-sum[num[rt<<1].suf-1]>=sum[r]-sum[num[rt<<1|1].suf-1])
 19         num[rt].suf=num[rt<<1].suf;
 20     else
 21         num[rt].suf=num[rt<<1|1].suf;
 22     long long v1=sum[num[rt<<1].vy]-sum[num[rt<<1].vx-1];
 23     long long v2=sum[num[rt<<1|1].vy]-sum[num[rt<<1|1].vx-1];
 24     long long v0=sum[num[rt<<1|1].pre]-sum[num[rt<<1].suf-1];
 25     if(v1>=v2){
 26         num[rt].vx=num[rt<<1].vx;
 27         num[rt].vy=num[rt<<1].vy;
 28     }
 29     else{
 30         num[rt].vx=num[rt<<1|1].vx;
 31         num[rt].vy=num[rt<<1|1].vy;
 32     }
 33     if(v0==sum[num[rt].vy]-sum[num[rt].vx-1]){
 34         if(num[rt<<1].suf<num[rt].vx){
 35         num[rt].vx=num[rt<<1].suf;
 36         num[rt].vy=num[rt<<1|1].pre;
 37         }
 38     }
 39      if(v0>sum[num[rt].vy]-sum[num[rt].vx-1]){
 40          num[rt].vx=num[rt<<1].suf;
 41         num[rt].vy=num[rt<<1|1].pre;
 42     }
 43 }
 44 void build(int rt,int l,int r){
 45      ll[rt]=l;
 46      rr[rt]=r;
 47      if(l==r){
 48         num[rt].pre=num[rt].suf=num[rt].vx=num[rt].vy=l;
 49         return;
 50      }
 51     int mid=(l+r)/2;
 52     build(rt<<1,l,mid);
 53     build(rt<<1|1,mid+1,r);
 54     pushup(rt,l,r);
 55 }
 56 Node query(int rt,int s,int t){
 57     if(ll[rt]==s&&rr[rt]==t)
 58         return num[rt];
 59      int mid=(ll[rt]+rr[rt])/2;
 60     if(mid>=t)return query(rt<<1,s,t);
 61     else if(mid<s)return query(rt<<1|1,s,t);
 62     else{
 63          Node temp1=query(rt<<1,s,mid);
 64          Node temp2=query(rt<<1|1,mid+1,t);
 65          Node temp;
 66     if(sum[temp1.pre]-sum[s-1]>=sum[temp2.pre]-sum[s-1])
 67         temp.pre=temp1.pre;
 68     else
 69        temp.pre=temp2.pre;
 70     if(sum[t]-sum[temp1.suf-1]>=sum[t]-sum[temp2.suf-1])
 71         temp.suf=temp1.suf;
 72     else
 73          temp.suf=temp2.suf;
 74     long long v1=sum[temp1.vy]-sum[temp1.vx-1];
 75     long long v2=sum[temp2.vy]-sum[temp2.vx-1];
 76     long long v0=sum[temp2.pre]-sum[temp1.suf-1];
 77     if(v1>=v2){
 78        temp.vx=temp1.vx;
 79        temp.vy=temp1.vy;
 80     }
 81     else{
 82          temp.vx=temp2.vx;
 83          temp.vy=temp2.vy;
 84     }
 85     if(v0==sum[temp.vy]-sum[temp.vx-1]){
 86         if(temp1.suf<temp.vx){
 87         temp.vx=temp1.suf;
 88         temp.vy=temp2.pre;
 89         }
 90     }
 91      if(v0>sum[temp.vy]-sum[temp.vx-1]){
 92         temp.vx=temp1.suf;
 93         temp.vy=temp2.pre;
 94     }
 95     return temp;
 96   }
 97 }
 98 int main(){
 99     int  cas=0,n,m,l,r;
100     long long tp;
101     while(~scanf("%d%d",&n,&m)){
102           memset(sum,0,sizeof(sum));
103         for(int i=1;i<=n;i++){
104             scanf("%lld",&tp);
105             sum[i]=sum[i-1]+tp;
106         }
107          build(1,1,n);
108         printf("Case %d:
",++cas);
109         for(int i=1;i<=m;i++){
110             scanf("%d%d",&l,&r);
111             Node ans=query(1,l,r);
112             printf("%d %d
",ans.vx,ans.vy);
113         }
114     }
115 
116 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3840103.html