我与旧事归于尽,来年依旧迎花开|

dayz_break

园龄:7个月粉丝:5关注:6

2024-10-06 18:47阅读: 10评论: 0推荐: 0

树剖总结

前言

最近被树剖整得很难受,于是有了这一篇总结。

灵感来源于这几道题:[Ynoi2017] 由乃的 OJ[SDOI2011] 染色[TJOI2015] 旅游

关于树剖

树剖解决的问题一般是动态且与树上的简单路径有关,就是将树上的问题转变到链上,然后用数据结构(线段树)来维护一些复杂信息。

一般解决树剖会遇到的瓶颈:

  1. 如何处理链上的情况。

  2. 查询时如何合并剖分开的链

下文主要记录处理第二个瓶颈的套路。

合并链

3 道题都有一个特点:合并链较难处理,有许多细节。

三个题有异曲同工之处,最后要将起点 u 跳过的链的答案 l,和跳完的 uv 中间的答案 mid,以及终点跳过链的答案 r 进行合并。

写法一

这三道题最后 uv 的形态会影响最后的答案,然而 uv 的形态无非就两种:一种 u 在上,一种 v 在上。但是有些时候要判一下 lr 是否记录过链的答案,否则会对答案产生影响。

[Ynoi2017] 由乃的 OJ为例,就有:

if(!flagl&&!flagr) memcpy(all,(dep[u]<=dep[v])?now.lans:now.rans,sizeof(all));
else if(id[u]<=id[v]) memcpy(all,(l*(now+r)).lans,sizeof(all));
else memcpy(all,((now+l)*r).lans,sizeof(all));

像旅游和染色就要更复杂一些,因为要判 lr 是否记录过链的答案。

写法二

先求出两点的最近公共祖先,然后将 uv 分别向 lcau,v 跳,求出左右的答案,这样不用判断形态,直接合并即可。代码会比第一种写法简单很多,但是常数比第一个略大。

小 trick 就是合并时重载运算符,结构体写初始化来简便代码。

本文作者:dayz_break

本文链接:https://www.cnblogs.com/dayz-break/p/18449283

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   dayz_break  阅读(10)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起