#sLPFybttg040504. 1563:染色
1563:染色
题目描述
给定一棵有 个节点的无根树和 个操作,操作共两类。
- 将节点 到节点 路径上的所有节点都染上颜色 ;
- 询问节点 到节点 路径上的颜色段数量,连续相同颜色的认为是同一段,例如 由三段组成:、、。
请你写一个程序依次完成操作。
输入格式
第一行包括两个整数 ,表示节点数和操作数;
第二行包含 个正整数表示 个节点的初始颜色;
接下来 行,每行包含两个整数 和 ,表示 和 之间有一条无向边;
接下来 行,每行描述一个操作:
C a b c:表示这是一个染色操作,把节点 到节点 路径上所有点(包括 和 )染上颜色 ;Q a b:表示这是一个询问操作,询问节点 到节点 路径上(包括 和 )的颜色段数量。
输出格式
对于每个询问操作,输出一行询问结果。
样例
输入样例 1
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
输出样例 1
3
1
2
样例解释
树结构(节点上数字为初始颜色):
1(2)
/ \
2(2) 3(1)
/|\
4 5 6
(2)(1)(1)
括号内为初始颜色。
操作解释:
Q 3 5:询问路径 上的颜色段。颜色依次为 ,段为 共 段。C 2 1 1:将路径 上所有节点染成颜色 。节点 和 变为颜色 。Q 3 5:路径 颜色为 ,只有 段。C 5 1 2:将路径 染成颜色 。节点 变为颜色 。Q 3 5:路径 颜色为 ,段为 共 段。
数据范围
- 所有颜色 为整数且在 之间。
时间限制:1000 ms
内存限制:524288 KB
提示
本题是树链剖分的进阶应用,需要维护区间颜色段数量。
基本思路:
- 对树进行树链剖分,将树上路径转化为若干条重链对应的区间。
- 用线段树维护每个区间:
- 区间左端点的颜色
- 区间右端点的颜色
- 区间内颜色段的数量
- 线段树需要支持区间覆盖(染色)和区间合并查询。
合并操作: 当合并两个相邻区间 和 时:
- 如果 ,则 (因为中间相邻颜色相同,段数合并时减少一段);
- 否则 。
- 合并后的 ,。
路径查询: 对于路径 ,在树链剖分跳链的过程中,我们分别从 和 向 LCA 跳,记录两段链的信息(注意方向)。最后将两段链的信息合并。因为跳链时顺序可能颠倒,需要分别维护从上到下的链段信息,然后正确合并。
染色操作: 路径覆盖,打懒标记即可。
时间复杂度: 。
注意:
- 颜色值范围较大,但颜色段只关心相邻是否相等,可以用整数存储。
- 树是无根的,可以任意指定根(如 )。
- 在跳链查询时,要注意合并的顺序,因为路径是有方向的。通常做法是用两个结构体分别记录从 向上跳的信息和从 向上跳的信息,最后将这两部分合并。