其他分享
首页 > 其他分享> > CF1718D 题解

CF1718D 题解

作者:互联网

设 \(k\) 为 \(a\) 中的空位数量。

首先咱们转化这个“相似”的条件,发现它其实是说,笛卡尔树的结构相同。

那么我们把p建笛卡尔树然后把a的数往上填。如果此时有上面小于下面就挂了(挂了:即每个询问答案都是NO)

然后对于中间的空,它需要 \(>\) 下面的最大值,并且 \(<\) 上面的最小值。设点 \(i\) 的这个区间为 \([l_i,r_i]\)

接下来我们发现,我们只需要把集合 \(S\) 中的数和 \(d\) 填到这些空里满足 \([l_i,r_i]\) 的限制即可。

为啥:

对于一条连续的空(中间没有确定值),此时它们的区间限制都相同,那就可以任意交换位置。因此只要排序后从下往上填,一定可以满足笛卡尔树上大下小的性质,并且和区间限制不冲突。

如果中间有确定值,那因为这个值的"分隔"作用,上面的区间的 \(l\) 肯定大于下面的区间的 \(r\)。此时如果区间条件被满足了,上面一定大于下面。

那接下来就变成了一个二分图匹配问题:一边是 \(k\) 个区间,一边是 \(k\) 个点。一个区间可以匹配区间内的所有点。给定 \(k\) 个点中的 \(k-1\) 个,问剩下的那个点 \(d\) 在哪些位置能使二分图有完美匹配。

“哪些位置”,结合手玩,一个初步的猜测是一段前缀/后缀,但是自己造数据手玩,发现不一定。但是手玩又发现,好像合法的 \(d\) 都是一段区间。这确实是对的。

假设现在有一个 \(d_0\) 满足 \(d_0\) 是一个合法位置。我们考虑此时的完美匹配,一定包含了 \(d_0\)。

考虑从 \(d_0\) 开始走二分图的“交错路”:走一个匹配边,然后一个不匹配边,然后一个匹配边,然后一个不匹配边... 走偶数次。如果能走到 \(d_1\),那么将途经的匹配边删去,并把不匹配边匹配上,它依然是一个合法匹配且匹配数不变。那么它就变成了一个包含 \(d_1\) 的完美匹配。从而此时的 \(d_1\) 也是一个合法的 \(d\)。

由于这张二分图的性质,显然,经过“交错路”可以走到的点一定是一段区间。从而答案是一段区间,求出区间的 \(l,r\) 即可判断了。

尽管它确实是一段区间,但我们暂时没什么办法搞出这个 \(l,r\)。总之,我们有必要先想一个问题:假设我们已知所有的点,如何求完美匹配呢?显然不能暴力Dinic,存在一个贪心做法:将点从小到大排序,每个点选择包含它的 \(r\) 最小的区间匹配。将区间按 \(l\) 排序后,相当于取一段前缀(由于点不断变大,这段前缀也是不断变大的)里 \(r\) 最小的并删除。用 pq 维护即可。

我原本想了一个用线段树单点修改区间求min+二分大力维护的做法。显然我是sb。

这个贪心确实是对的,但它的问题在于扩展性不好。点中有一个变成了未知的点,那整个匹配都被打乱了。

我们也可以用这个做法求出 \(k-1\) 个点的匹配,然后剩下的那个区间是 \(d\) 的一段可行区间。但这不一定是 \(d\) 的整个可行区间,它可能只是一段子段

求出这个可行区间之后,在可行区间的左右分别二分好像是对的。虽然区间不能直接二分,但我们知道了区间中的一段,那么在这一段的左边一定是一段后缀满足,右边一定是一段前缀满足。

但这个做法是 \(\log^2\) 的,并且实现起来好像比较复杂,也许可以试试。

这里还有另一个做法就是,我先默认把 \(d\) 匹配到这里剩下的区间里,然后DFS走交错路,看能到哪些点。但是注意到左到右是区间连边,因此需要线段树优化建图。这就是我一开始写的做法。它 确实 是一个 \(\log\),但是它常数巨大且巨难写。

你也许会想到一个错误的贪心:按 \(l\) 排序,每次取区间内最小的点。

它为什么不对呢?这个贪心只便宜了 \(l\),如果下一个区间的 \(r\) 突然变小,那我们上一次取不太小的点,把最小的点留给这个区间,也许是更优的。

反例:区间 \([1,4],[2,3]\),点 \(3,4\)。这个做法会把 \(3\) 给 \([1,4]\),然后 \([2,3]\) 就没有匹配了。

我们发现它的扩展性很好(如果是对的),我们可以先对 \(k-1\) 个点做贪心。如果贪心的过程中区间里没有点了,就说明这个区间应该和 \(d\) 匹配。

它怎么改成对的呢?事实上按 \(r\) 从小到大排序就行了。可以证明,如果二分图存在完美匹配,那用这个办法一定可以取到一个。(证明思路就是假设当前如果取的不是区间里最小的,而是在后面取了这个最小的,这样有匹配,那么现在取最小的后面取大的那个也是可以的,不断这样交换就可以证明,如果存在一个完美匹配,一定可以用这种办法取到其中一个)

用这个策略不断的取,直到遍历当前区间时,区间里没点了,此时 \(d\) 就一定在这个区间里面了。由于我们是按 \(r\) 排序的,容易发现,此时这个区间的 \(r\) 就是最大的 \(d\) 。(很容易反证:如果 \(d\) 大于当前区间的 \(r\) 一定不行)。

一个值得注意的细节是,上述贪心过程中只能失配一次,这一次恰好用来确定 \(d\);如果失配了两次或以上,说明无解。

对称的,我们发现按 \(l\) 从大到小排序每次取区间里最大的也是对的。这样取一遍,区间里没点的时候,这个区间的 \(l\) 就是最小的 \(d\)。

然后这样就得到了合法的 \(d\) 的最大最小值,每次判给定的 \(d\) 是否在该区间里就行。注意中途做的时候判一下无解。

两次贪心用set即可简单维护,复杂度是小常数一个 \(\log\)。

标签:二分,匹配,一个,题解,CF1718D,一段,区间,贪心
来源: https://www.cnblogs.com/LightningUZ/p/16667963.html