前言
本来想找一道树剖的题的发现LCT可做…
侵删(博客习惯…
题目
我们来看一道正解为树剖的题目…
题目描述
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
输入
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
输出
对于每个询问操作,输出一行答案。
样例输入
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
样例输出
3
1
2
提示
数 N<=105,操作数 M <= 105,所有的颜色C为整数且在[ 0 , 109 ]之间。
解题
树链剖分
正解是树剖…
树链剖分解题思路
一道很接近板子的树剖
加上记录一条线段最左边的颜色和最右边的颜色
进行维护 sum 值的时候判断颜色是否相同…
树链剖分虽然代码很长但是跑的比较快的…
是时候展现一波一百六十多行的代码
树链剖分AC代码2008ms
1 |
|
又难打又难修…
LCT
乍一看LCT也能写?!
LCT解题思路
一道很接近模板的LCT,我觉得这道题用来练LCT也是不错的
比一般的模板多出了几个元素需要我们去维护
基本操作是差不多的而且还少了 cut 操作,但是 push_down 与 update 的写法也不太一样需要我们去想
总的来说,我们需要判断一个节点的左儿子最右边的颜色和右儿子最左边的颜色是不是和这个节点相同
所以我们多出的元素就是一条链最左边的颜色和最右边的颜色需要记录
最初的赋值也是要注意的,这次的标记我们不再使用一个而是需要两个了
另外区间翻转的时候不能只翻转左儿子和右儿子,记录的最左边的颜色和最右边的颜色也是需要翻转的
关于上面的判断我觉得代码还是很需要想的毕竟不是那么容易就能实现的
还有一件事我不知道为什么在 link 里把 find(x)==find(y)去掉我就AC否则RE
相较之下LCT代码量虽短但是需要想的东西很多细节也很多代码不容易打好而树剖就比较无脑了…
我开始就以为无脑打LCT就没仔细想 push_down 和 update
所以我们来看一下一百行的LCT…
有什么不会就在代码里找吧
LCT AC代码4740ms
1 | // luogu-judger-enable-o2 |
后记
事实证明,树剖代码量很大…(接近5K…
但是树剖跑的比LCT快…(2008ms与4740ms
但是我树剖修了好久(代码量太大不容易debug…
一定是我太菜了虽然deLCT的时候也有一些不明不白的锅…
欢迎指正…联系方式如下
qq: 953559040
微博: IncinblePan
洛谷: SherlockPan