题目
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 n-1 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 m 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
1 | 6 5 |
Sample Output
1 | 3 |
HINT
$N \leq 10^5, M \leq 10^5$,所有的颜色C为整数且在$[0, 10^9]$之间。
解题思路
这道题思路应该是很好想到的——树链剖分+线段树
显然,合并两个颜色段时,如果合并点两侧颜色相同,那么颜色段数量为左右两段数量之和再减一,否则就是它们的和。根据这个基本性质——
线段树维护3个值:颜色段数量(cnt)、左端颜色(lcol)、右端颜色(rcol),于是tr[id].cnt = tr[lid].cnt + tr[rid].cnt - (tr[lid].rcol == tr[rid].lcol);
树链剖分询问时(即往上“跳”时),记录一下上一次询问的端点颜色,如果本次询问的相应端点颜色在合并点处与上次询问端点颜色相等,就要减一。
至此本题解决。
复杂度$O(n\log ^2n)$
Code
1 |
|