带修改的区间最大子段和

维护一个带有两个操作的数据结构:

1.询问[L,R]之间的最大子段和

2.单点修改

 

题解:

正解:线段树/平衡树

线段树做法:

维护三个东西vl,vr,max,sum:

vl,vr分别表示必须包含区间左\右端点的最大子段和,max为该区间的最大子段和,sum为区间和

然后转移三个变量:

 

Tree[node].max=max(Tree[ls].max,max(Tree[rs].max,Tree[ls].vr+Tree[rs].vl))
Tree[node].sum=Tree[ls].sum+Tree[rs].sum
Tree[node].vl=max(Tree[ls].vl,Tree[ls].sum+Tree[rs].vl)
Tree[node].vr=max(Tree[rs].vr,Tree[rs].sum+Tree[ls].vr)

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #define ls (node<<1)
 8 #define rs (node<<1|1)
 9 using namespace std;
10 const int N=500005,inf=2e8;
11 int n,m,a[N];
12 struct Segtree{
13     int max,vl,vr,sum,fg;
14 }Tree[N<<3];
15 void updata(int node){
16     Tree[node].max=max(Tree[ls].max,max(Tree[rs].max,Tree[ls].vr+Tree[rs].vl));
17     Tree[node].sum=Tree[ls].sum+Tree[rs].sum;
18     Tree[node].vl=max(Tree[ls].vl,Tree[ls].sum+Tree[rs].vl);
19     Tree[node].vr=max(Tree[rs].vr,Tree[rs].sum+Tree[ls].vr);
20 }
21 void build(int l,int r,int node){
22     Tree[node].fg=true;
23     if(l==r){
24         Tree[node].sum=a[l];
25         Tree[node].max=a[l];
26         Tree[node].vl=a[l];
27         Tree[node].vr=a[l];
28         return ;
29     }
30     int mid=(l+r)>>1;
31     build(l,mid,ls);build(mid+1,r,rs);
32     updata(node);
33 }
34 void add(int l,int r,int node,int ps,int to){
35     if(l>ps || r<ps)return ;
36     if(l==r){
37           Tree[node].sum=to;
38         Tree[node].max=to;
39           Tree[node].vl=to;
40         Tree[node].vr=to;
41         return ;
42     }
43     int mid=(l+r)>>1;
44     add(l,mid,ls,ps,to);add(mid+1,r,rs,ps,to);
45     updata(node);
46 }
47 Segtree query(int l,int r,int node,int sa,int se){
48     if(sa<=l && r<=se)return Tree[node];
49     int mid=(l+r)>>1;
50     if(sa>mid)return query(mid+1,r,rs,sa,se);
51     if(se<=mid)return query(l,mid,ls,sa,se);
52     Segtree t,lson,rson;
53     lson=query(l,mid,ls,sa,se);rson=query(mid+1,r,rs,sa,se);
54     t.vl=max(lson.vl,lson.sum+rson.vl);t.vr=max(rson.vr,lson.vr+rson.sum);
55     t.max=max(lson.vr+rson.vl,max(lson.max,rson.max));
56     return t;
57 }
58 void work()
59 {
60     scanf("%d%d",&n,&m);
61     for(int i=1;i<=n;i++)
62         scanf("%d",&a[i]);
63     build(1,n,1);
64     int fg,x,y;
65     while(m--){
66         scanf("%d%d%d",&fg,&x,&y);
67         if(fg==2)add(1,n,1,x,y);
68         else printf("%d\n",query(1,n,1,x,y).max);
69     }
70 }
71 
72 int main()
73 {
74     work();
75     return 0;
76 }

 

转载于:https://www.cnblogs.com/Yuzao/p/7351766.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值