暴力求解

1.最简单的方法是:在主函数中添加一个循环 

进行 r-l+1次单点修改实现区间修改,对于单个元素修改时间复杂度为 O(log2(n))
所以对于单个区间修改的时间复杂度为 O(n*log(n)),甚至比朴素的模拟算法还慢

for(int p=l;p<=r;++p)
UpdateTree(p,value); 

2.延时标记 lazy tag
延时标记就是在递归的过程中,如果当前区间被需要,修改的区间完全覆盖,那么就要停止递归,并且在上面做一个标记

3.但是这个信息没有更新到每个元素(即叶子结点),下次查询的时候可能没法得到足够的信息。之前在一个区间上打了一个标记,这个标记不仅是这个结点的性质,此性质作用于整个子树中,假设我们另一个查询中包含了,当前区间的子孙区间,这个标记也要对之后的查询产生影响

lazy tag

1.如果对线段树进行单点更新,都是在叶子节点中实现,不会对后续节点产生影响

2.如果当前区间被需要修改的目标区间完全覆盖,打一个标记 
如果下一次的查询或更改包含此区间,那么将这个标记分解,并传递给左右儿子

3.延时标记在需要时,才向下传递信息,如果没有用到,则不再进行操作
为了完成这种操作,可以在结构体中增加一个add数组存储区间的延时变化量

4.通俗的解释 lazy的意思,比如现在需要对[a,b]区间进行加 C操作,
那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点
它的节点标记为 rt,这时 tree[rt].l==l&&tree[rt].r==r这时我们可以进一步
更新此时rt节点的sum[rt]的值,sum[rt]+=(ll)c*(r-l+1);

5.关键的地方:如果此时按照常规的线段树的update操作,这时候还应该更新
rt子节点的sum[]值,而lazy思想恰恰是暂时不更新rt子节点的sum[]值,
到此时就 return,直到下一次需要用到rt子节点的值得时候才去更新,
这样避免许多无用的操作,从而节省时间

6.PushUp(rt);通过当前节点rt把值递归向上更新到根节点
PushDown(rt);通过当前节点rt递归向下去更新rt子节点的值

rt表示当前子树的根,也就是当前所在的节点

解题模板

1.定义结构体来存储每个节点的子节点数值的总和,
add用来记录该节点的每个数值应该加多少
tree[i].l,tree[i].r分别表示某个节点的左右区间,都是闭区间

__int64 sum[N<<2],add[N<<2];
struct Node
{int l,r;int mid(){return (l+r)>>1;}
} tree[N<<2];

2.PushUp(rt);通过当前节点rt把值递归向上更新到根节点

void PushUp(int rt)
{sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

3.PushDown(rt);通过当前节点rt递归向下去更新rt子节点的值

rt表示当前子树的根,也就是当前所在的节点

void PushDown(int rt,int m)
{if(add[rt]){add[rt<<1] += add[rt];add[rt<<1|1] += add[rt];sum[rt<<1] += add[rt] * (m - (m>>1));sum[rt<<1|1] += add[rt] * (m>>1);add[rt] = 0;}
}

4.建立线段树

void build(int l,int r,int rt)
{tree[rt].l = l;tree[rt].r = r;add[rt] = 0;if(l == r){scanf("%I64d",&sum[rt]);return ;}int m = tree[rt].mid();build(lson);build(rson);PushUp(rt);
}

5.update函数,lazy思想主要用于这里

通俗的解释 lazy的意思,比如现在需要对[a,b]区间进行加 C操作,
那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点
它的节点标记为 rt,这时 tree[rt].l==l&&tree[rt].r==r这时我们可以进一步
更新此时rt节点的sum[rt]的值,sum[rt]+=(ll)c*(r-l+1);

关键的地方:如果此时按照常规的线段树的update操作,这时候还应该更新
rt子节点的sum[]值,而lazy思想恰恰是暂时不更新rt子节点的sum[]值,
到此时就 return,直到下一次需要用到rt子节点的值得时候才去更新,
这样避免许多无用的操作,从而节省时间

void update(int c,int l,int r,int rt)
{if(tree[rt].l == l && r == tree[rt].r){add[rt] += c;sum[rt] += (__int64)c * (r-l+1);return;}if(tree[rt].l == tree[rt].r) return;PushDown(rt,tree[rt].r - tree[rt].l + 1);int m = tree[rt].mid();if(r <= m) update(c,l,r,rt<<1);else if(l > m) update(c,l,r,rt<<1|1);else{update(c,l,m,rt<<1);update(c,m+1,r,rt<<1|1);}PushUp(rt);
}

6.query函数,也就是用这个函数来求区间和

第一个if还是区间的判断和前面update的一样,到这里就可以知道答案了,所以就直接return。

接下来的查询就需要用到rt子节点的值了,由于我们用了Lazy操作,这段的数值还没有更新,因此我们需要调用PushDown函数去更新之,满足if(add[rt])就说明还没有更新。

__int64 query(int l,int r,int rt)
{if(l == tree[rt].l && r == tree[rt].r){return sum[rt];}PushDown(rt,tree[rt].r - tree[rt].l + 1);int m = tree[rt].mid();__int64 res = 0;if(r <= m) res += query(l,r,rt<<1);else if(l > m) res += query(l,r,rt<<1|1);else{res += query(l,m,rt<<1);res += query(m+1,r,rt<<1|1);}return res;
}

线段树 区间更新 区间查询模板题  POJ3468

线段树之延时标记(区间修改)及lazy思想相关推荐

  1. 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 a ...

  2. 树状数组的区间修改+查询

    首先看树状数组是用来求前缀和比较方便的一种数据结构 sum[i] = Sigma a[i] =Sum(bit[x]) 而区间修改也不难实现 就是引入一个差分数组del del[i]表示对i~n的修改 ...

  3. kb-07线段树-12--二分查找区间边界

    1 /* 2 hdu4614 3 本题刚开始想能不能记录该区间最前面开始的点,最后面的点,区间空的数量:但是病不行 4 然后线段树的本质是区间操作,所以!这题主要就是区间的空的全放满,只要定出区间的边 ...

  4. 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】...

    模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: ----------------------------------------- ...

  5. poj 2892---Tunnel Warfare(线段树单点更新、区间合并)

    题目链接 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensiv ...

  6. 树状数组之区间修改单点查询

    树状数组的区间修改单点查询 树状数组其实本质还单点修改区间查询,但是我们怎么延伸到这个呢,我们建立一个差分数组, 比如:                a[10]={4, 6, 7, 5, 1, 6, ...

  7. 二维树状数组模板(区间修改+区间查询)

    二维树状数组模板(区间修改+区间查询) 例题:JOIOI上帝造题的七分钟 一共两种操作: \(L\ x_1\ y_1\ x_2\ y_2\ d\):把\((x_1,y_1)\),\((x_2,y_2) ...

  8. 线段树动态开点区间加区间求和

    线段树动态开点区间加区间求和 题目来源: 陕西师范大学第七届程序设计竞赛网络同步赛 H. 万恶的柯怡 思想: 保证叶子节点被完整的覆盖,需要开节点,就把左右儿子都开出来,其余和普通线段树一样. tip ...

  9. splay + 线段树 ---- P3765总统选举 [带修改的动态区间众数 摩尔投票+n棵splay]

    题目链接 题目大意: 解题思路: 1.摩尔投票法: 题意是找n个数内出现次数大于n/2的数 保证存在这个数用的方法叫做摩尔投票法 首先我们注意到这样一个现象: 在任何数组中,出现次数大于该数组长度一半 ...

最新文章

  1. 学习动力之“学习金字塔 (爱德加•戴尔)”理论
  2. ubuntu18安装nginx没有生成各类目录文件问题解决
  3. 文巾解题 627. 变更性别
  4. 数组字符串转化成数组与eval函数
  5. 《世界已无法阻挡Python入侵!》(附学习资源)
  6. 多表关联查询_【函数007】 EXCEL多表关联查询实战
  7. 对话华为云专家,摆脱无意义“内卷”
  8. Focus Stacking
  9. 【R包】2018年数据科学前20名R包
  10. 香港科技大学理学院数据建模硕士学位项目MSc DDM 项目介绍×申请指南
  11. 100道初级网络工程师测试题
  12. VUE中nextTick( )函数思维导图
  13. Word中参考文献导入Endnote
  14. Home Assistant 家庭助理安装
  15. 数字人民币真的来了 六年历程全回顾
  16. 【原创】微信双开是定时炸弹?关于非越狱iOS上微信分身高危插件ImgNaix的分析
  17. Android软件开发面试题,安卓面试题库
  18. 广式粤语VS港式粤语
  19. Calendar加減月份、年份-月底的处理逻辑
  20. Shell脚本交互:自动输入密码

热门文章

  1. [iOS常见问题] 关于使用QQ做第三方登录的问题!
  2. windows常用命令行整理
  3. 我的MIDAS中间层服务器运行效果图
  4. html5语音云,搜狗语音云开放平台
  5. java语言程序设计你_清华大学出版社-图书详情-《Java语言程序设计》
  6. c语言里的%p的作用,C语言中geiwei=m%10什么意思,求解!
  7. tf keras Dense源码解析
  8. python区块链开发_10个开源的Python区块链项目
  9. android 相册选择视频和图片格式,Android获取文件类型是图片还是视频
  10. Dreanmwear能做php模板吗,PHPword模板的使用