之前说了线段树的点更新和区间求和。其实点更新是区间更新的一种最基础的做法。我们把一个点想像成一个区间的话,不就是最简单的区间更新了嘛。
为什么要把区间更新和点更新分开来看呢?假如我们对区间[l,r]进行更新,我们对这一段区间进行r-l+1次点更新不就行了嘛?这样结果确实没有错误,但是这样的话,时间复杂度会非常高,区间更新的题目如果这么做肯定会超时的。那么我们就引进了区间更新了。
这里引入了一个标记数组,lazy[maxn<<2]。lazy数组是区间更新中的精髓所在,lazy的意思就是懒的意思。我们对于每一次区间更新,我们并不直接一次更新到底,而是用lazy标记着更新了多少,等到需要的时候,我们再更新。
简单的说就是,我们把向下的修改先储存起来,而对于每个查询我们在向上传递答案的时候加上这些修改的值。
那区间更新+区间求和来说:
对于任意一段[l,r]区间加上一个数v,然后对任意区间求和。

inline void pushup(int cur)//pushup和之前的含义是一样的
{p[cur].sum=p[cur<<1].sum+p[cur<<1|1].sum;
}
inline void pushdown(int cur)//重点重点重点
{if(p[cur].lazy)//如果存在延迟更新的话{p[cur<<1].lazy+=p[cur].lazy;p[cur<<1|1].lazy+=p[cur].lazy;//左右儿子节点的lazy加上父亲节点的lazyp[cur<<1].sum+=(p[cur<<1].r-p[cur<<1].l+1)*p[cur].lazy;p[cur<<1|1].sum+=(p[cur<<1|1].r-p[cur<<1|1].l+1)*p[cur].lazy;//每个节点都加上了lazy,这样的话,一共就加上了区间长度个lazy。p[cur].lazy=0;//执行完上面的操作后就将lazy清零。}
}

区间更新模板

const int maxx=1e5+100;
struct node{int l;int r;int sum;int lazy;
}p[maxx<<2];
inline void pushup(int cur)
{p[cur].sum=p[cur<<1].sum+p[cur<<1|1].sum;
}
inline void pushdown(int cur)
{if(p[cur].lazy){p[cur<<1].lazy+=p[cur].lazy;p[cur<<1|1].lazy+=p[cur].lazy;p[cur<<1].sum+=(p[cur<<1].r-p[cur<<1].l+1)*p[cur].lazy;p[cur<<1|1].sum+=(p[cur<<1|1].r-p[cur<<1|1].l+1)*p[cur].lazy;p[cur].lazy=0;}
}
inline void build(int l,int r,int cur)//一如既往的建树操作
{p[cur].l=l;p[cur].r=r;p[cur].sum=p[cur].lazy=0;if(l==r){p[cur].sum=a[l];return ;}int mid=l+r>>1;build(l,mid,cur<<1);build(mid+1,r,cur<<1|1);pushup(cur);
}
inline void update(int l,int r,int cur,int v)
{int L=p[cur].l;int R=p[cur].r;if(l<=L&&R<=r)//如果当前区间在要更新的区间中,就可以停止递归,转为lazy标记{p[cur].sum+=(R-L+1)*v;p[cur].lazy+=v;return ;}pushdown(cur);//现在要更新下面的子节点了,因此我们要先将之前的lazy标记下放,否则会出错。int mid=L+R>>1;if(r<=mid) update(l,r,cur<<1,v);else if(l>mid) update(l,r,cur<<1|1,v);else {update(l,mid,cur<<1,v);update(mid+1,r,cur<<1|1,v);}pushup(cur);
}
inline int query(int l,int r,int cur)//求和操作,和update的含义是一样的。
{int L=p[cur].l;int R=p[cur].r;if(l<=L&&R<=r) return p[cur].sum;pushdown(cur);int mid=L+R>>1;if(r<=mid) return query(l,r,cur<<1);else if(l>mid) return query(l,r,cur<<1|1);else return query(l,mid,cur<<1)+query(mid+1,r,cur<<1|1);
}

线段树的魅力并不在于这里,而是线段树和其他的算法巧妙的结合在一起,例如DP以及矩阵等,会产生很多有意思的算法。除此之外,线段树的区间合并以及扫描线等也是很有意思的。
努力加油a啊,(o)/~

数据结构之线段树进阶(区间更新lazy标记)相关推荐

  1. java-HDU1698(线段树的区间更新,和区间查询)

    HDU1698: 题目意思: Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  2. (转)线段树的区间更新

    原文地址:http://blog.csdn.net/zip_fan/article/details/46775633 写的很好,昨天刚刚开始写线段树,有些地方还不是很明白,看了这篇博文,学会了数组形式 ...

  3. poj 2528 Mayor's posters(线段树 离散化 区间更新 贴海报)

         这个题目本来对大神来说可能是水题, 对我就不行了,昨晚非折腾到下半夜一点 搞定, 并且可以总结出 ,只有把问题想清楚,或着看人家解题报告自己把问题和代码思路 搞清楚,才能谈的上调bug,否则 ...

  4. 【HDU - 3974】 Assign the task (dfs序 + 线段树维护 区间更新+ 单点查询)

    题干: There is a company that has N employees(numbered from 1 to N),every employee in the company has ...

  5. 【POJ - 3468 】 A Simple Problem with Integers (线段树模板 区间更新 + 区间和查询)(不能树状数组或差分数组)

    题干: You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o ...

  6. 【HDU - 5649】DZY Loves Sorting(线段树,区间更新区间查询,思维,01缩数变换,线段树分割)

    题干: DZY has a sequence a[1..n]a[1..n]. It is a permutation of integers 1∼n1∼n. Now he wants to perfo ...

  7. POJ 3468 A Simple Problem with Integers(线段树:区间更新)

    http://poj.org/problem?id=3468 题意: 给出一串数,每次在一个区间内增加c,查询[a,b]时输出a.b之间的总和. 思路: 总结一下懒惰标记的用法吧. 比如要对一个区间范 ...

  8. HDU 4267 线段树 离散点区间更新, 自叶子节点至根单点查询

    题意: n个数字 下面n个数字表示数列 2个操作 1 [u, v]  k  add [u,v ]区间 (u点要计算)每隔k个位置,该数字+add 2 pos 询问 pos下标的值(下标从1开始) 思路 ...

  9. Find the median(线段树离散化+区间更新)

    题目链接:https://ac.nowcoder.com/acm/contest/887/E 链接:https://ac.nowcoder.com/acm/contest/887/E 来源:牛客网 F ...

最新文章

  1. 联想 k2450 温度、耗电试验
  2. php 中文 处理,PHP处理中文字符串截取
  3. tomcat常用的优化和配置
  4. mysql删除账户后不能使用_MySQL删除普通用户
  5. boost::boyer_myrvold_params::kuratowski_subgraph用法的测试程序
  6. wait和notify使用例子
  7. 教你如何成为解决问题的高手
  8. 【转】RAX,eax,ax,ah,al 关系
  9. javascript Array对象基础
  10. 求1+2+3+4+...+n
  11. 实践中 XunSearch(讯搜)更新索引方案对比
  12. Learning-MySQL【4】:表的操作管理和 MySQL 的约束控制
  13. IBM:云存储三步走
  14. CAD转图片如何调整输出格式?
  15. c++ 头歌实训 第四关 日历打印
  16. Unity人物角色动画系统学习总结
  17. python吃内存吗_python – 为什么泡菜吃内存?
  18. FCES2019第二天 | BY AI,AI技术赋能教育的N种可能
  19. 单元测试技巧之PowerMock
  20. Win10系统QQ无法登录,00001错误解决办法

热门文章

  1. envi插件大津法_IDL打开科学数据集
  2. 软件质量保证计划_如何做好软件项目的质量管理?
  3. 关于 epoch、 iteration和batchsize的区别
  4. 文件包含(include require)
  5. 计算机系统中数据加工过程中,数据库系统复习题-第1章绪论
  6. mfc140dll 丢失 微软常用运行库_微软常用运行库合集 2020.9月(32amp;64位)
  7. python 计算过程图片_[Python图像处理]九.图像形态学相关运算
  8. if test 多条件_if函数进阶篇 嵌套+多条件判断
  9. c语言 sizeof_c语言详解sizeof
  10. php 如何设计索引_Mysql学习浅谈mysql的索引设计原则以及常见索引的区别