本题求的是指定区间的最大连续子段和,和单点修改
(方法略复杂,线段树与动规杂交,但空间较小)
我们可以用结构体维护每个二分区间的总和(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 }