原地址:https://blog.csdn.net/sunyutian1998/article/details/79618316

个人感觉区间合并是线段树各种应用中变形最多 也是比较难琢磨的一种

(以下以求01序列中最长连续1为例)

tree[cur].left代表以区间左端点为起点的连续段的长度 tree[cur].right代表右边 tree[cur].all代表该区间内最长的连续段

通过这三个变量的组合 对于每一个区间一般有四个值供我们使用

1 tree[cur].left代表以该区间左端点为起点的连续段的长度(左连续段)2 tree[cur].right代表以该区间右端点为终点的连续段的长度(右连续段)3 tree[2*cur].right+tree[2*cur+1].left 代表包含该区间中点的连续段的长度 这是个隐含值(中间连续段)4 tree[cur].all代表该区间内最长连续段 其值不止要从左右子节点的最长连续段中择最大 还要考虑该区间的中间连续段即 tree[cur].all=max(tree[2*cur].right+tree[2*cur+1].left,max(tree[2*cur].all,tree[2*cur+1].all));对于tree[cur].all的取值可以这样理解 如果两个子区间合并后产生了新的连续段 那一定是tree[2*cur].right+tree[2*cur+1].left的值 即中间连续段 如果没有那就只能在两个子区间的最长连续段择优了

区间合并关键在于pushup函数的构造 详见代码注释(以求01序列中最长连续1为例)

void pushup(int cur)
{tree[cur].left=tree[2*cur].left;//当前区间的左区间的左端点肯定也是当前区间的左端点 所以以当前区间的左端点为起点的最长连续1长度肯定包含其左区间的对应值 这一部分值先记下来if(tree[cur].left==tree[2*cur].r-tree[2*cur].l+1) tree[cur].left+=tree[2*cur+1].left;//再判断一下当前这些连续的1是不是已经贯穿了整个左区间 和有区间接轨 如果是的话 必须把右孩子的对应值也加上(如果右孩子对应区间全为1 那么当前区间也会全为1 这种情况也是很有可能的)/*比如[1,8]区间 (1 1 1 1) (1 1 0 1)在未pushup时tree[2*cur].left==4,tree[2*cur].right==4,tree[2*cur].all==4tree[2*cur+1].left==2,tree[2*cur+1].right==1,tree[2*cur+1].all==2执行完tree[cur].left=tree[2*cur].left后tree[cur].left==4 但显然以当前区间的左连续段的长度还需要算上右区间中的一部分所以要执行tree[cur].left+=tree[2*cur+1].left 然后tree[cur].left==6即为正确结果*/tree[cur].right=tree[2*cur+1].right;//右连续段的处理同上if(tree[cur].right==tree[2*cur+1].r-tree[2*cur+1].l+1) tree[cur].right+=tree[2*cur].right;tree[cur].all=max(tree[2*cur].right+tree[2*cur+1].left,max(tree[2*cur].all,tree[2*cur+1].all));//显然当前区间最长连续段要从左右区间的最长连续段取最大值 但这样就足够了吗?//tree[cur].all的值不止要从左右子区间的最长连续段中择最大 还要考虑该区间隐含的"中间连续段"/*比如[1,12]区间 (1 1 1 0 1 1) (1 1 0 1 1 1)在未pushup时tree[2*cur].left==3,tree[2*cur].right==2,tree[2*cur].all==3tree[2*cur+1].left==2,tree[2*cur+1].right==3,tree[2*cur+1].all==3只考虑从左右区间的最长连续段取最大值的话 即执行tree[cur].all=max(tree[2*cur].all,tree[2*cur+1].all)之后tree[cur].all==3但显然中间有四个连续的1被漏掉了*/return;
}

下面是做过的一些类型题总结

1 求一块满足条件的最左边的空白空间 poj3667

2 求某个元素所在连续段的长度(也可求左右端点) hdu1540

3 求某个连续段的起始位置 hdu2871

4 区间合并在扫描线求周长中的应用 hdu1828

5 区间合并与异或操作结合 以及求整个区间内最长连续段的长度 hdu3911 hdu3397

6 求区间最长连续上升序列 hdu3308

转载于:https://www.cnblogs.com/zhenglw/p/9507886.html

【转载】线段树 区间合并 小结相关推荐

  1. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  2. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  3. Tunnel Warfare(HDU1540+线段树+区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...

  4. poj-3667(线段树区间合并)

    题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...

  5. HDU3308 线段树区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...

  6. CodeForces - 1539F Strange Array(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,规定位置 iii 的贡献是:设 x=a[i]x=a[i]x=a[i],选择一个包含 iii 的区间 [l,r][l,r][l,r],将其中 ...

  7. 牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)

    题目链接:点击查看 题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作: 1 pos k b:将 ...

  8. 2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并

    传送门 文章目录 题意: 思路: 题意: 题面挺绕口的,还是看原题比较好. 大概的意思就是让你从给定的区间中选择一个以左端点为起点的一个上升子序列,让后将这些下标存下来,在bbb中将这些位置拿出来后, ...

  9. HDU1540(线段树区间合并)

    很经典的一道题,线段树区间合并非常好的一道入门题,每个节点保存区间连续1的最大左串长度,最大右串长度,以及区间最大长度(常规的三种信息维护),更新操作时注意push_up函数,针对不同的问题,push ...

最新文章

  1. java 日志 生成_Java日志(转)
  2. 互联网协议 — SCTP 流控制传输协议
  3. Android监听SD卡文件变化
  4. numpy.tril详解
  5. spring boot整合shiro继承redis_spring-boot-plus集成Shiro+JWT权限管理
  6. 安卓蓝牙键盘切换输入法_采用国产机械轴,三种连接模式轻松切换,TT G521上手体验...
  7. Oracle创建表空间及用户
  8. phphstudy运行不了网站_网站SEO优化之如何维护网站权重?
  9. 有没有和我一样从来不和亲戚联系的人?
  10. 【线程安全】—— 单例类双重检查加锁(double-checked locking)
  11. 水印相机定位不准确怎么办_选好镜头 选好3D四轮定位仪
  12. Gateway 网关 (二) 全局过滤器
  13. Maven第8篇:按需构建
  14. cesium多边形描边_cesium--绘制多边形polygon
  15. Linux修改系统时间
  16. Kali无线渗透加油破解无线
  17. Java list转tree,tree转list(递归实现)
  18. Java架构师成长之路
  19. Hexo博客配置笔记
  20. npm 报错 : npm ERR! Maximum call stack size exceeded npm ERR! A complete log of this run can be found

热门文章

  1. matlab保存数据用什么指令_Matlab数据处理——数据的保存和读取方法操作
  2. typora html代码无效,Typora优化-适合不懂CSS代码的小白
  3. 负载均衡轮询算法和服务器性能,负载均衡算法
  4. python坐标轴拉伸_python-Matplotlib垂直拉伸histogram2d
  5. java多线程阶乘_【java学习记录】11.用多线程实现阶乘的计算过程和结果的读取(thread类ReadThread )...
  6. mysql doc插入数据_如何向MySQL数据库的表中录入数据.doc
  7. java字典类_Java字典类
  8. Python中的numpy.sum()
  9. spring aop示例_具有AOP事务管理的Spring ORM示例
  10. C++还有前景吗?做服务器这一块可以吗?