询问区间是否同色
来源:互联网 发布:广州用友java面试题 编辑:程序博客网 时间:2024/05/22 01:57
下面再看一个例子:有一条直线,每次把其中一段染成某种颜色,要求输出最终的染色
情况。
首先,可以把所有操作所涉及到的坐标离散化,从而可以用整数区间来表示直线上的线
段。然后,由于现在的问题不涉及区间的查询,只涉及区间的修改,我们不需要考虑“如何
合并两条线段的信息”这一问题,而只需考虑“如何在树上作标记以快速维护每个位置的颜
色”。不难发现,这个题目中,每个节点不需要记录前面意义上的“值”,而只需要记录前面
所说的“标记”。我们定义,一个节点上如果作了标记,就说明它所表示的区间里只有同一种
颜色,而这种颜色是由标记所表示的;如果没有作上标记,就说明需要看它的儿子节点,才
能确定它的颜色。
对于一开始完全没有染色的情况,直接把整个区间拆成O(log n)个被操作区间,然后分
别做上标记即可。但是如果遇到这样的情况,如节点[0,3]已经被标记了,但是我们这次修改
了[3,5],那么[0,3]的标记就不再有效,但是如果直接删除的话,那么[0,2]这个范围内的颜色
又记错了。这就需要我们再次使用“标记向下传”的办法,这次的传的方法比较简单,直接把
标记覆盖传给两个儿子节点,然后清空父亲节点的标记即可。回到刚才的第一句话,“对于
一开始完全没有染色的情况”,事实上甚至我们都不需要完全的初始化,只需要把根节点做
上一个“初始颜色”的标记,就行了。
在本题中加入随时询问某个位置的颜色,不需要对树进行任何更改即可完成。但是如果
加入了随时询问某一段是否同色,标记就不能这样随便传了:我们需要在一个节点所代表的
一段内是同色的时候,确保它作了标记。 这样,在每次修改过程结束后,我们还需要再检查 :
是不是这个节点其实可以打上标记?伪代码如下所示:
function change(v, l, r, color) // 把[l,r]范围内修改成color
if [l,r]和[v.l,v.r]没有交集
退出
end if
if l = v.l AND r = v.r
v.mark <- color
// 直接作上标记
退出
end if
if NOT v.mark = 未标记
v.lch.mark <- v.mark
v.rch.mark <- v.mark
v.mark <- 未标记
// 标记往下传
end if
change(v.lch,l,r,color)
change(v.rch,l,r,color)
if v.lch.mark = v.rch.mark AND NOT v.lch.mark = 未标记
v.mark <- v.lch.mark
// 更新v的标记状态
end if
end function
从这个例子可以看出来, “一个区间的颜色”这个性质, 既符合“相邻区间的信息能合并”,
又符合“标记可以向下传”。因此,没有绝对的“值”与“标记”的区分。所有的东西都是存在节
点里的信息,通过不同的方式得到维护。前面的例子把两者分开,只是着重强调这两个性质
分别的意义而已。
情况。
首先,可以把所有操作所涉及到的坐标离散化,从而可以用整数区间来表示直线上的线
段。然后,由于现在的问题不涉及区间的查询,只涉及区间的修改,我们不需要考虑“如何
合并两条线段的信息”这一问题,而只需考虑“如何在树上作标记以快速维护每个位置的颜
色”。不难发现,这个题目中,每个节点不需要记录前面意义上的“值”,而只需要记录前面
所说的“标记”。我们定义,一个节点上如果作了标记,就说明它所表示的区间里只有同一种
颜色,而这种颜色是由标记所表示的;如果没有作上标记,就说明需要看它的儿子节点,才
能确定它的颜色。
对于一开始完全没有染色的情况,直接把整个区间拆成O(log n)个被操作区间,然后分
别做上标记即可。但是如果遇到这样的情况,如节点[0,3]已经被标记了,但是我们这次修改
了[3,5],那么[0,3]的标记就不再有效,但是如果直接删除的话,那么[0,2]这个范围内的颜色
又记错了。这就需要我们再次使用“标记向下传”的办法,这次的传的方法比较简单,直接把
标记覆盖传给两个儿子节点,然后清空父亲节点的标记即可。回到刚才的第一句话,“对于
一开始完全没有染色的情况”,事实上甚至我们都不需要完全的初始化,只需要把根节点做
上一个“初始颜色”的标记,就行了。
在本题中加入随时询问某个位置的颜色,不需要对树进行任何更改即可完成。但是如果
加入了随时询问某一段是否同色,标记就不能这样随便传了:我们需要在一个节点所代表的
一段内是同色的时候,确保它作了标记。 这样,在每次修改过程结束后,我们还需要再检查 :
是不是这个节点其实可以打上标记?伪代码如下所示:
function change(v, l, r, color) // 把[l,r]范围内修改成color
if [l,r]和[v.l,v.r]没有交集
退出
end if
if l = v.l AND r = v.r
v.mark <- color
// 直接作上标记
退出
end if
if NOT v.mark = 未标记
v.lch.mark <- v.mark
v.rch.mark <- v.mark
v.mark <- 未标记
// 标记往下传
end if
change(v.lch,l,r,color)
change(v.rch,l,r,color)
if v.lch.mark = v.rch.mark AND NOT v.lch.mark = 未标记
v.mark <- v.lch.mark
// 更新v的标记状态
end if
end function
从这个例子可以看出来, “一个区间的颜色”这个性质, 既符合“相邻区间的信息能合并”,
又符合“标记可以向下传”。因此,没有绝对的“值”与“标记”的区分。所有的东西都是存在节
点里的信息,通过不同的方式得到维护。前面的例子把两者分开,只是着重强调这两个性质
分别的意义而已。
- 询问区间是否同色
- 树状数组模板区间更新 区间询问
- 树状数组模板区间更新 区间询问
- 树状数组(单点修改,区间询问)
- 树状数组--区间加单点询问
- poj 3225【线段树--区间更新,XOR,区间询问】
- Splay解决区间问题[单点更新,区间最值询问]
- CF 52C Circular RMQ(区间更新,区间询问)
- poj3468树状数组之区间更新+区间询问
- 【线段树】PKU2777 区间更新区间询问(位优化)
- 树状数组模板区间更新 区间询问大全
- [CodeVS1082] 线段树练习3(区间修改+询问区间和)
- POJ 2528 线段树区间查找区间询问
- POJ 3468(线段树,区间加减 询问区间和)
- HihoCoder 1078(线段树,区间覆盖 询问区间和)
- C#关闭程序询问是否退出
- js中询问是否要删除
- 实例5:询问是否退出的对话框
- Linux中修改文件来设置网络连接
- iPhone5官网剖析 看苹果公司如何用设计元素
- ajaxjson与EXT实用练习
- C++string报未引入和CString互转
- C中的预编译宏定义
- 询问区间是否同色
- 如何让MAC OS X下将所有隐含文件都显示出来
- 从 C++ 到Objective-C
- 编程珠玑学习笔记1
- C#获取进程打开关联的文件集合
- UI应遵循的三大网站设计原则
- C#反射
- #ifndef与#pragma once
- LoadImage BitBlt 学习笔记