【CH4301】Can you answer on these queries III
这是一道用线段树维护区间最大子段和的题目
本题的关键在于如何维护区间最大子段和。对于线段树的每一个节点,我们定义四个域:sum,l,r,maxx分别表示这个区间的和、以这个区间左边为起点的最大子段和是多少、以这个区间右边为起点的最大子段和是多少、这个区间的最大子段和是多少。当我们用这个区间的两个子区间合并他的时候,就会有如下结论:
- a[now].sum=a[now<<1].sum+a[now<<1|1].sum;
- a[now].l=max(a[now<<1].l,a[now<<1].sum+a[now<<1|1].l);
- a[now].r=max(a[now<<1|1].r,a[now<<1|1].sum+a[now<<1].r);
- a[now].maxx=max(max(a[now<<1].maxx,a[now<<1|1].maxx),a[now<<1].r+a[now<<1|1].l);
有了这个,这道题就容易多了,本题为单点修改,将难度降低了一下,用线段树按照上述步骤处理即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long ll; 7 int n,m; 8 struct node { 9 int sum,l,r,maxx; 10 }a[500010<<2]; 11 inline int read() { 12 int ret=0; 13 int op=1; 14 char c=getchar(); 15 while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();} 16 while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar(); 17 return ret*op; 18 } 19 inline void pushup(int now) { 20 a[now].sum=a[now<<1].sum+a[now<<1|1].sum; 21 a[now].l=max(a[now<<1].l,a[now<<1].sum+a[now<<1|1].l); 22 a[now].r=max(a[now<<1|1].r,a[now<<1|1].sum+a[now<<1].r); 23 a[now].maxx=max(max(a[now<<1].maxx,a[now<<1|1].maxx),a[now<<1].r+a[now<<1|1].l); 24 } 25 void build(int now,int l,int r) { 26 if(l==r) { 27 a[now].l=a[now].r=a[now].maxx=a[now].sum=read(); 28 return ; 29 } 30 int mid=l+r>>1; 31 build(now<<1,l,mid); 32 build(now<<1|1,mid+1,r); 33 pushup(now); 34 } 35 void updata(int now,int l,int r,int x,int val) { 36 if(l==r&&x==l) { 37 a[now].l=a[now].r=a[now].maxx=a[now].sum=val; 38 return ; 39 } 40 int mid=l+r>>1; 41 if(x<=mid) updata(now<<1,l,mid,x,val); 42 else updata(now<<1|1,mid+1,r,x,val); 43 pushup(now); 44 } 45 node query(int now,int l,int r,int x,int y) { 46 if(x<=l&&r<=y) return a[now]; 47 int mid=l+r>>1; 48 if(y<=mid) return query(now<<1,l,mid,x,y); 49 else if(x>mid) return query(now<<1|1,mid+1,r,x,y); 50 node ret; 51 node reta=query(now<<1,l,mid,x,y); 52 node retb=query(now<<1|1,mid+1,r,x,y); 53 ret.sum=reta.sum+retb.sum; 54 ret.l=max(reta.l,reta.sum+retb.l); 55 ret.r=max(retb.r,retb.sum+reta.r); 56 ret.maxx=max(max(reta.maxx,retb.maxx),reta.r+retb.l); 57 return ret; 58 } 59 int main() { 60 n=read(); m=read(); 61 build(1,1,n); 62 while(m--) { 63 int op=read(),x=read(),y=read(); 64 if(op==2) { 65 updata(1,1,n,x,y); 66 } 67 else { 68 if(x>y) swap(x,y); 69 printf("%d\n",query(1,1,n,x,y).maxx); 70 } 71 } 72 return 0; 73 }