带修改的区间最大子段和
2017-08-12 21:59
330 查看
维护一个带有两个操作的数据结构:
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.询问[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)
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #define ls (node<<1) #define rs (node<<1|1) using namespace std; const int N=500005,inf=2e8; int n,m,a ; struct Segtree{ int max,vl,vr,sum,fg; }Tree[N<<3]; void updata(int node){ 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); } void build(int l,int r,int node){ Tree[node].fg=true; if(l==r){ Tree[node].sum=a[l]; Tree[node].max=a[l]; Tree[node].vl=a[l]; Tree[node].vr=a[l]; return ; } int mid=(l+r)>>1; build(l,mid,ls);build(mid+1,r,rs); updata(node); } void add(int l,int r,int node,int ps,int to){ if(l>ps || r<ps)return ; if(l==r){ Tree[node].sum=to; Tree[node].max=to; Tree[node].vl=to; Tree[node].vr=to; return ; } int mid=(l+r)>>1; add(l,mid,ls,ps,to);add(mid+1,r,rs,ps,to); updata(node); } Segtree query(int l,int r,int node,int sa,int se){ if(sa<=l && r<=se)return Tree[node]; int mid=(l+r)>>1; if(sa>mid)return query(mid+1,r,rs,sa,se); if(se<=mid)return query(l,mid,ls,sa,se); Segtree t,lson,rson; lson=query(l,mid,ls,sa,se);rson=query(mid+1,r,rs,sa,se); t.vl=max(lson.vl,lson.sum+rson.vl);t.vr=max(rson.vr,lson.vr+rson.sum); t.max=max(lson.vr+rson.vl,max(lson.max,rson.max)); return t; } void work() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); int fg,x,y; while(m--){ scanf("%d%d%d",&fg,&x,&y); if(fg==2)add(1,n,1,x,y); else printf("%d\n",query(1,n,1,x,y).max); } } int main() { work(); return 0; }
相关文章推荐
- Spoj 6779 Can you answer these queries VII 树链剖分 在树上任意路径的最大子段和 区间修改点权
- spoj 1716...动态区间的最大连续子段和问题...点修改...
- Spoj 1716 Can you answer these queries III 线段树 单点修改 区间求最大子段和
- 伸展树(插入区间,修改区间,区间置数,区间反转,区间求和,连续最大和)BZOJ1500
- caioj1099 线段树(区间修改+求区间最大值
- [kuangbin带你飞]专题七 线段树 B - I Hate It(单点修改,区间最大值)
- HDU-1754 I Hate It (线段树裸题 splay模板 单点修改 区间询问最大值)
- [线段树] [求区间最大] [定点修改]
- gym101138J(树链剖分,线段树维护区间连续子段最大和,好题)
- hdu 5280 Senior's Array 修改区间和最大
- SPOJ GSS1 静态区间求解最大子段和
- RMQ -- 不修改的权值的求区间最大最小值
- 【树状数组】【单点修改区间求和】【区间修改单点查询】【单点修改区间最大值查询】
- 求区间最大子段和(线段树)
- 线段树 - 区间修改 - 最大值
- 线段树区间修改 懒惰标记 维护和、最大值、最小值
- 【线段树】 区间最大值(不带修改)
- 算法训练 操作格子 线段树 单点修改,求区间和,区间最大值
- I Hate It HDU - 1754(线段树单点修改,区间求最大值模板)
- ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 I.Minimum(线段树_单点修改,查询区间最大最少值)