好难一道题呜呜,补题补了半个月

前置知识点:

  • 二分

  • 网络流

  • 虚树

  • 线段树优化建图

  • 树链剖分

题意

给 $n$ 个结点的树 ( $n \leq 20000$),每个结点给定一个颜色 $c$

对于每个结点 $u$ 任选一个 $d_u$

假设以 $u$ 为根的子树中共有 $k_u$ 个颜色为 $d_u$ 的结点

那么这个结点的值为 $k_u\times d_u$

求所有结点 值 的 $MEX$ (最小的 不在集合内的 非负整数)

题解

暴力

容易想到(赛场上想到)这个数据范围甚至可以 $O(n^2)$ 暴力求出每个结点各种颜色有几个

枚举每种颜色,然后树上跑 dfs 即可

然后暴力网络流建图,二分答案,如果能跑满流即满足条件

因为是二分图,时间复杂度 $O(n\sqrt{m} \log{n})$

唯一的缺陷就是空间复杂度,也即边数 $m = n^2$

正解

废话

官方给出了可行的方案是线段树优化建图 (什么玩意给我整蒙了)

但学习一下发现所谓的线段树优化建图并不难(吧

但我还是不会嘛,官方给出的题解也是感觉很大一部分都没讲

参考了牛客上的一巨佬用户题解,然后又去学了虚树(我怎么什么都不会)

咕咕了差不多半个月,王老师队出了题解,我总算开始懂了

正文

定义 为上述 $k_u\times d_u$

对于每种颜色建立虚树,每个结点到他父亲的区间 [结点, 父亲) 左闭右开区间

这个区间内结点的子树中当前颜色结点的数量相同,即这些点可以连向一种值

(这里不要忘了虚树顶端到树根节点1的连边)

此处即可线段树优化建图,在寻找 [结点, 父亲) 时可以用树剖往上跳

复杂度分析

虚树 时间 $O(n\log n)$ 空间 $O(n)$ 虚树的点数总和是 $O(n)$

树剖往上眺每个结点 $O(\log n)$ 总的复杂度 $O(n\log n)$

线段树优化建图总每条边 $O(\log n)$ 总的 $O(n\log^2n)$

网络流点数 $O(n)$ 边数 $O(n\log^2n)$ 复杂度$O(玄学)$

优化

这里有个奇妙的操作,即在网络流图中,对于树上每条重链

该重链中所有父亲结点向儿子结点连一条边(不包括重链底部的最后一个点)

如果在寻找 [结点, 父亲) 时树剖向上跳跳过了一条重链顶端

就可以把你在这条重链上起跳点往对应的值连INF边即可

就不必对整个区间线段树优化建图

为什么呢?因为起跳点到重链顶端这个区间的点都可以流向对应值

因为父亲往儿子建边,起跳点上面的点就可以流下来到起跳点再到对应值

而该重链上起跳点下面的点则不会流到对应值

另外对于二分,可以跑残余网络

也即当前二分点 $mid$ 满足条件的话,就在残余网络上加边继续跑

如果不满足,就重新建图,或者题解的方法是保存之前网络流图,然后回退(详情见代码

那么二分的这个 $\log n$ 复杂度应该是能去掉

再分析复杂度

除了没有跳过重链顶端的那次,也就是最后一次,最多只会有一次

除了这次用线段树优化建图 $O(\log n)$ 其他连边边数都是 $O(1)$

一次树剖跳 $O(\log n)$ 所以每个区间连的边数就是 $O(\log n)$

网络流点数 $O(n)$ 边数 $O(n\log n)$ 复杂度 $O(能过)$

小声逼逼

我引以为傲的 $ISAP$ 算法竟然被 $Dinic$ 吊打了至少20

不知道为什么 $ISAP$ 就妥妥 $TLE$ 呗, $Dinic$ 就跑贼快

果然网络流只有 $O(能过)$ 和 $O(不能过)$

牛客巨佬用户题解有张图挺好的,建议看下,详情见文末链接

代码

参考资料

线段树优化建图

网上某博客

题解

官方题解

BonVoyage 大爹队的题解

牛客用户 XLor 的题解