FA 科技:一种基于换根 + DFS 序的点分治下下位替代

起因:cjx 暑假集训的时候出了道题,老师说可以点分治。但是我最初的想法其实是换根处理,但怎么想发现都行不通,因为要同时维护 DFS 序和权值。于是就没想了。后来 10.5 和 xyh 进行长达 30s 的讨论 导游的工作 那题,说了我这个想法,xyh 觉得有道理,对要求解的问题具体化,于是我才想出了分块这一数据结构。并在 xyh 的指导下进行卡常。但其实这个方法已经被发明过了。Tree 那道题的题解里有提到过。

这个方法的复杂度是 O(n×P),其中 P 为一个多项式,代表你使用的数据结构的复杂度。也就是说,如果你的 P 可以足够好,这个方法甚至可以是点分治的平替。

例题 1:BNDSOJ 1502 导游的工作

Method 1:暴力换根

我们钦定 1n 中的每一个点为根。对于每一个根 u 算出整个树上每个点的深度,判断有多少个点的深度小于等于 c 即可。这是显然的,时间复杂度为 O(n2)

Method 2:分块优化换根

基本的思想还是 暴力统计。我们只是在用数据结构强行优化这个暴力。

考虑 树上换根动态规划 的思想。统计每个点的答案贡献。前提是你对换根法有了较为深刻的理解。但我们知道,如果把根从 u 换到儿子 v,每个点的深度都会随之改变。而且这个改变关于原来点的编号不连续。但好消息是,我们在这里并不关注原先的点的编号是什么。

那我们怎样快速修改这个“不连续”的区间呢?如果你知道 树链剖分。那你一定知道它的下位替代—— DFS 序线段树 吧。其实就是根据 子树的 DFS 序连续 这一特性,把不连续的编号转化为连续的 DFS 序进行修改。在这一题里也同样是这么使用的。

但是这题我们并不能使用线段树。因为我们要的操作是这两种:

  1. 区间加减 w
  2. 全局询问小于等于 c 的 depth 的个数

其实第二个的全局我们可以加强成区间。你会发现这个东西基本等价于 P2801 教主的魔法。于是我们可以使用 分块 维护。

于是时间复杂度为 O(n×P)=O(nlognn)

例题 2:P3806 【模板】点分治 1

这个因为时限卡的过死于是不能满分,虽然说暴力也可以拿到 60 pts,但是我想说这个换根的方法是远优于暴力的。

这个题其实和上面那个题没有本质区别。还是换根,然后询问全局有没有等于 c 的数,依然可以块内二分解决。

最主要的不同就是把询问离线下来,每次换根的时候都处理一次 Q 个询问即可。

例题 3:P4178 Tree

这个就纯纯与导游的工作那题没有任何区别,所以我认为导游的工作那题也是紫。

就是把求最大变成全局统计小于等于 k 的点对了啊。

注意如果换根统计出来的答案是 ans,则真正的答案应该为 ansn2

例题 4:P2634 [国家集训队] 聪聪可可

稍微变一下形,这题的复杂度是 O(nn),因为没有块内排序和块内二分。

就是询问树上边权和为 3 的倍数的路径数。考虑每一块维护三个值。分别代表深度模 30,1,2 的个数。然后每次加 w 或减 w,其实就相当于加 0/1/2。加 0 不用管,加 1/2 就相当于模 30,1,2 的个数互相交换。

注意散块的处理要尤为注意,就是因为散块,我们还要维护一个区间加再模 3 的 tag。修改的时候散块也是最麻烦的。

主要难点都是在分块。换根本身没啥难的。

posted @   DataEraserQ  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示