P5912 JAS 题解

传送门

题意;找出最浅的点分树。

发现这是一个等价问题:给每个结点一个标号,当两个结点标号相同时,它们的路径上必有严格更小的标号。如果找到了这样一种标号方法,每个结点的标号就是它的深度。

同时我们还可以把每个结点的标号 x 对应到 n+1x,也是一一对应。问题又变成路径上必有严格更大的标号。

给出一个贪心构造标号的方法:先让所有叶子为 1,然后对于非叶子结点,它的标号为不与它的子树冲突的最小数。

那我们如何判断一个结点 u 能填哪些数?

定义一个结点 x 对于 u 是 “溢出的”:如果 x 到 (x 所在的 u 的子树的根)的路径上所有点权都 <x,称结点 x 是溢出的。

子树的溢出的结点构成子树的溢出集合。

显然 u 不能取每个子树溢出集合中的任何一个数。同时如果两颗子树中有两个溢出的结点权值相等为 y,则 u 的权值必须 >y

然后是这个贪心的证明。

f(s1sk) 为当儿子们的溢出集合为 s1sk 时,u 能填的最小数。F(s1sk) 为用 f(s1sk) 填了 u 后,u 子树的溢出集合。

两个引理:

  1. uf(s1sk) 时,u 子树的溢出集合最小。这里的最小是指如果把集合看作二进制数时最小。后面的集合比大小也是这么定义。

  2. skskF(s1sk1,sk)F(s1sk1,sk)

若这两条引理成立,贪心就能简单证出来:

根据 2,要 u 的溢出集合最小,要使所有儿子的溢出集合最小。

而根据 1,填 f() 能使溢出集合最小。则贪心得证。

引理 1 证明:

观察到 u 填入 x 后,u 的溢出集合就是把儿子的溢出集合并起来,然后删去所有小于 x 的数。

T=s1sk。如果把集合视作二进制数,u 填入 x 就相当于在 x 位上变成 1,比 x 位低的都改成 0。这样显然是 x 尽量小才好。

引理 2 证明:

ts1sk1 中最大的出现在至少两个集合中的数(t=0 表示无公共元素),T=s1sk1 再去掉 t 的数。

发现若 t>0,则 skt 的元素都无意义,所以所有集合都可以去掉后 t 位。也就是可以假设 t=0,即没有公共元素。那此时的 T=s1sk1,因为没有 t 的数了。

再简化一下命题,因为引理 2 其实表示了一个单调性质,于是我们可以假设 sk=sk+1

w 为最小的不属于 sk 的标号。

  1. 情况一,skT 有元素大于 w

    因为有交集大于 w,所以 f() 一定大于 w。而 F() 为填了 f() 的溢出集合,因为 f()>w,比 f() 低的位都会变成 0(不再溢出)。

    sk,sk=sk+1 的区别就是:sk 的最低位一直到 w 的前一位都是 1,第 w 位是 0sk+1 的最低位一直到 w 的前一位都是 0,第 w 位都是 1。其他的都一样。

    但是 f() 把较低位的都变成 0 了,所以 sk,sk=sk+1 最终算出来的 F 相等。

  2. 情况二,不满足情况一且 wT

    因为 f() 选择的位不能出现在任何儿子的溢出集合,所以 f() 选择的位一定在所有儿子的溢出集合中都是 0,也就等价于 T 的位上和 sk(sk) 的位上都是 0。(t=0=>T=s1sk1

    因为 wT,所以 T 的第 w 位为 1

    考虑 f(s1sk1,sk)=f(T,sk),因为 skw 位以下都是 1,第 w 位为 0,所以 f(T,sk) 不能在 w 及以下。(第 w 位及以下都有非 0 的)因此 f(T,sk) 是在第 w 位以上找到的第一个 T,sk 都是 0 的位。

    T,sk+1 的第 w 位都是 1,重复了,所以 f(T,sk+1) 必须高于第 w 位。所以 f(T,sk+1) 是在第 w 位以上找到的第一个 T,sk+1 都是 0 的位。

    因为第 w 位以上 sk,sk+1 相同。所以这种情况下 f(T,sk)=f(T,sk+1)

  3. 情况三,不满足情况一且 wT

    T 的第 w 位为 0

    因为 sk,T 的第 w 位都是 0,所以 f(T,sk) 就是第 w 位,F(T,sk) 的第 w 位以上为 Tsk,第 w 位为 1,第 w 位以下为 0

    F(T,sk)=(Tsk)+1

    因为 sk+1 的第 w 位为 1sk+1 比第 w 位更高的位与 sk 相等。所以 F(T,sk+1) 至少第 w 位是 1,比 w 高的位和 Tsk 相同。而比 w 低的位 F(T,sk) 全是 0,所以 F(T,sk+1)F(T,sk)

综上,引理 2 也得证了。

所以贪心方法是:每个叶节点都标号 1,其他结点的权值为 f(sons)。标号结束后最大的标号就是答案。

计算溢出集合、找出最低的都是 0 的位可以在 O(logn) 的时间里做完。(位运算应该能到 O(1)

posted @   FLY_lai  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示