题解:P11983 [JOIST 2025] 展览会 3 / Exhibition 3(暂无数据)
Petit_Souris · · 题解
难度已经远比我能独立做出的题高了。不过回顾一下,几个 trick 的叠加也并非无迹可寻。好题,值得学习。
Hint 1:你能编出一个多项式复杂度做法吗?
看到字典序想到逐位贪心。我们考虑从大到小枚举
对于每个
判断最小覆盖是一个经典贪心问题,每次选择右端点最小的区间,在其右端点处放一个点即可。
Hint 2:每次选出的区间形态如何?
显然是一段前缀,加上一些零散的区间。这看起来是一句废话,但是我们考虑那一段前缀后面一个位置,他不能选说明加入他之后
这样后面的区间就必须满足加入之后,不会增加最小覆盖点数。
Hint 3:如何找到这个前缀?直接二分为什么不可行?
二分意味着我们花了至少序列总长的代价去删除一些元素。因此如果每次只删一个复杂度就起飞了。
但是我们可以考虑先倍增。找到最大的
Hint 4:如何判断加入一个区间之后是否需要多一个点覆盖他?
这个结论应该是经典的,可惜我还没见过这样做的题目。有同学知道类似的题目可以在评论区告知我。/kt
我们考虑正反做两遍贪心,求出每个点所在的范围
Hint 5:一个区间加入之后,tl,tr 会发生怎样的变化?
以
这样做的修改次数实际上是
Hint 6:利用上面的性质编出正解。
找到前缀后,我们只需要快速找出编号最小的,可以加入的区间。
一个简单的想法是用一个小根堆维护所有的编号。这样我们每次对于一个
但是这样有一个严重的问题就是,一个区间可能会被放进去很多遍,就退化成
找有交的最小编号可以分讨二维偏序关系,用两个线段树维护。
最后整理一下这部分的过程:
- 先得到
tl,tr ,对于每个[tl_j,tr_j] ,先把所有包含他的,还未使用过的区间拎出来标记上。 - 接下来,对于每个
[tl_j,tr_j] ,找到与其有交的最小编号,加入小根堆。 - 每次取出最小的编号,加入答案。并且重新松弛对应的
j ,找到新的最小值。
最终时间复杂度为
实现上细节比较多,一定要理清楚再开始写,写完一部分 debug 掉对应的问题。参考代码。