标签:取出 贪心 def 情况下 要求 区间 and 取数 遍历
这个问题可以重新表述为:
给你 $n$ 个区间 $[a_i, b_i]$,$1 \le a_i \le b_i \le n$。
这里,区间 $[l, r]$ 指的是正整数集合 $\{l, l+1, \dots, r\}$。
从第 $i$ 个区间中取一个数 $x_i$,也就是说要求 $a_i\le x_i \le b_i$。
这是一个经典问题。有两个贪心做法:
将区间按右端点从小到大排序,按此顺序遍历这些区间,在每个区间中取所能取的最小的那个数。举例言之,有三个区间 $[1, 1], [1, 3], [2, 2]$,排序后是 $[1, 1], [2, 2], [1, 3]$。在 $[1,1]$ 中取 $1$,$[2, 2]$ 中取 $2$,$[1,3]$ 中取 $3$。
这个做法有 $n$ 个步骤。
$S$ 是一个 multiset,初始为空。
第一步:将左端点等于 $1$ 的区间的右端点加到 $S$ 中。若 $S$ 里的最小值小于 $1$,则无解,否则从 $S$ 里的最小值对应的那个区间中选取 $1$,并把最小值从 $S$ 中删除。
第二步:将左端点等于 $2$ 的区间的右端点加到 $S$ 中。若 $S$ 里的最小值小于 $2$,则无解,否则从 $S$ 里的最小值对应的那个区间中选取 $2$,并把最小值从 $S$ 中删除。
第 $k$ 步:将左端点等于 $k$ 的区间的右端点加到 $S$ 中。若 $S$ 里的最小值小于 $k$,则无解,否则从 $S$ 里的最小值对应的那个区间中选取 $k$,并把最小值从 $S$ 中删除。
此贪心算法的正确性证明:https://codeforces.ml/blog/entry/76555?#comment-613974
容易看出,multiset 可换成小顶堆。
顺着上述贪心做法二的思路我们可以判断出取数的方案是否唯一:
在第 $k$ 步中如果 $S$ 中至少有两个元素,并且 $S$ 中的最小值大于 $k$——设 $S$ 中的最小值和次小值对应的区间编号分别为 $i$,$j$——那么我们看能否从区间 $j$ 中取 $k$。如何判断呢?
可以这样做:假设正常情况下从区间 $j$ 取出的数是 $x_j$,我们看一下 $x_j$ 能否从区间 $i$ 中取出。
此解法来自 https://codeforces.ml/blog/entry/76555?#comment-613946
正确性我不会证明。
参考实现:https://codeforces.ml/contest/1348/submission/81636889
如何求有多少个不同的排列?
标签:取出 贪心 def 情况下 要求 区间 and 取数 遍历
原文地址:https://www.cnblogs.com/Patt/p/12976892.html