题解 luoguP4513 【小白逛公园】

本题求的是指定区间的最大连续子段和,和单点修改

(方法略复杂,线段树与动规杂交,但空间较小)

我们可以用结构体维护每个二分区间的总和(to),从左边开始的最大连续子段和(le), 从右边开始的最大连续子段和(ri) 及该区间的最大连续子段和(v)

再用全局量maxn存当前的最大和(只包含横跨两个或两个以上区间的情况),maxa存以当前区间结尾的最大和,这个依据是cx函数的深搜顺序是从左到右

cx函数的返回值是各个子区间的各自的最大和中的最大值,最后输出的是它与maxn 比较的结果 

坑点::a可能大于b

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int n,m,maxa,maxn;
  4 struct ee
  5 {
  6     int le,ri,v,to;
  7 }a[2000004];
  8 
  9 void init()
 10 {
 11     freopen("1.txt","r",stdin);
 12 }
 13 
 14 void js(int l,int r,int z)//建树 
 15 {
 16     if(l==r)
 17     {
 18         scanf("%d",&a[z].v);
 19         a[z].le=a[z].v;
 20         a[z].ri=a[z].v;
 21         a[z].to=a[z].v;
 22         return;                                            
 23     }
 24     int mid=(l+r)>>1;
 25     int zz=z<<1;
 26     int y=zz|1;
 27     js(l,mid,zz);
 28     js(mid+1,r,y);
 29     a[z].v=max(a[zz].v,max(a[zz].ri+a[y].le,a[y].v));
 30     a[z].le=max(a[zz].le,a[zz].to+a[y].le);
 31     a[z].ri=max(a[y].ri,a[y].to+a[zz].ri);
 32     a[z].to=a[zz].to+a[y].to;
 33 }
 34 
 35 int cx(int l,int r,int x,int y,int z)
 36 {
 37     if(x<=l&&y>=r) 
 38     {
 39         if(x==l)
 40         {
 41                 maxa=a[z].ri;
 42                 maxn=maxa;
 43         }
 44         else
 45         {
 46             if(y!=r)
 47             {
 48                 maxn=max(max(maxn,a[z].ri),max(maxa+a[z].to,maxa+a[z].le));
 49                 maxa=max(maxa+a[z].to,a[z].ri);//这里是保证以当前区间结尾的子段和最大 
 50             }
 51             else
 52             {
 53                 maxa=maxa+a[z].le;
 54                 if(maxa>maxn) maxn=maxa;
 55             }//动规 
 56         }
 57         return a[z].v;
 58     }
 59     int mid=(l+r)>>1;
 60     int zz=z<<1;
 61     int maxans=-1<<31;
 62     if(x<=mid) maxans=cx(l,mid,x,y,zz);
 63     if(y>mid) maxans=max(maxans,cx(mid+1,r,x,y,zz|1));
 64     return maxans;
 65 }
 66 
 67 void xg(int l,int r,int x,int y,int z)//修改时和建树很像 
 68 {
 69     if(l==r)
 70     {
 71         a[z].v=y;
 72         a[z].le=a[z].v;
 73         a[z].ri=a[z].v;
 74         a[z].to=a[z].v;
 75         return;
 76     }
 77     int mid=(l+r)>>1;
 78     int zz=z<<1;
 79     int yy=zz|1;
 80     if(x<=mid) xg(l,mid,x,y,zz);
 81     else xg(mid+1,r,x,y,yy);
 82     a[z].v=max(a[zz].v,max(a[zz].ri+a[yy].le,a[yy].v));
 83     a[z].le=max(a[zz].le,a[zz].to+a[yy].le);
 84     a[z].ri=max(a[yy].ri,a[yy].to+a[zz].ri);
 85     a[z].to=a[zz].to+a[yy].to;//维护
 86 }
 87 
 88 void readdata()
 89 {
 90     scanf("%d%d",&n,&m);
 91     js(1,n,1);
 92     for(int i=1;i<=m;i++)
 93     {
 94         int k,a,b;
 95         scanf("%d%d%d",&k,&a,&b);
 96         if(k==1) 
 97         {
 98             int c;
 99             if(a>b) c=cx(1,n,b,a,1);
100             else c=cx(1,n,a,b,1);
101             printf("%d\n",max(c,maxn));
102         }
103         else xg(1,n,a,b,1);
104     }
105 }
106 
107 int main()
108 {
109     //init();
110     readdata();
111     return 0;
112 }

猜你喜欢

转载自www.cnblogs.com/Mandy-H-Y/p/10317961.html
今日推荐