party[bzoj5404]
题面
题解
分析数据范围
首先一看 $c$ 比较小,再看颜色数也只有 $1000$,这些十分有用,以后必定会用到。
分析题意
为了尽快到齐,那就一定会到达这 $c$ 的人的 $LCA$ 处。
这时我们需要求出每个人到达 $LCA$ 的特产有哪些。
考虑第1步做法
我们并不关心这些特产的出现次数,只关心有没有出现就可以了。
那就是状态压缩,每一位表示有没有,然后or起来就可以了。
这个东东可以用 bitset 搞一搞,一次的时间是 $O(\frac{m}{w})$,其中 $w$ 为 $64$,大概是在 $15$ 左右。
那么如何求出一个点到它某个祖先的出现颜色的集合呢?
维护树上前缀和?显然不行,这个or操作不支持删除。
那么只能暴力树剖了,然后上线段树,时间复杂度 $O(q\frac{m}{w}\log^2n)$,不太行。
这时需要一个技巧:我们可以维护每个点到其重链顶端的路径的集合。
那么就只需要一直跳重链,跳到最后和 $LCA$ 同重链的时候再用线段树就可以了。
这样就可以省掉一个 $log$ 的时间。
考虑第2步做法
求出了上面那个东西,接下考虑如何通过这 $c$ 个集合求得答案。
这个答案是满足单调性的,试试二分?
考虑一个人选 $k$ 种颜色是否可行。
无法很快地判断出来,先试试暴力(假设只有一个询问)?
建一个二分图,$X$ 集合中 $ck$ 个点,每个人有 $k$ 个点;$Y$ 集合有 $m$ 个点,代表每种颜色。
若第 $i$ 个人的集合中出现了颜色 $j$ ,则 $i$ 的 $k$ 个点都连一条边到 $j$。
转换成判断是否存在完美匹配。
根据Hall定理,每个 $X$ 集合的子集连出去的点的集合大小必须大于等于该子集的大小。
只要一个人中的某个点出现在该子集中,那么这个人的所有点都要出现该子集中。
所以有 $2^c-1$ 种情况需要考虑。
那么就对于所有的 $S\subseteq X$ 有 $|S|k\leq |N_g(S)|$,也就是 $k\leq \min(\frac{|N_G(S)|}{|S|})$
那么二分的步骤都省略了,答案即为 $\min(\frac{|N_G(S)|}{|S|})$。
复杂度
记 $t=\frac{m}{w}$,则时间复杂度 $O(nt\log n+qt(c\log n+2^c))$
代码
1 |
|