do_while_true

一言(ヒトコト)

wqs 二分

wqs 二分

强制必须选恰好 \(i\) 个物品的价值是 \(ans_i\),要求出恰好选 \(m\) 的答案也就是 \(ans_m\)

如果 \(ans\) 是凸的(差分单调,这里仅讨论上凸即差分不增),那么可以二分一个直线的斜率,让这条直线尝试切这个凸包,如果切点横坐标在 \(m\) 左侧,就减小斜率,否则增大斜率。最终切点的纵坐标即为答案。

二分一个斜率之后,怎么找到切点?大家都知道一条固定斜率的直线切这个凸包,第一个切到的点满足其截距最大。

也就是现在有直线 \(y=kx+b\)\(k\),找到一个 \((i,ans_i)\) 使得 \(b\) 最大。

移项一下得到 \(ans_i-ki=b\),考虑这个的实际含义,选出 \(i\) 个物品的同时,要减去物品个数 \(\times k\) 的代价。

那么给每个物品一个 \(-k\) 的价值偏移,当成没有物品个数的限制来找到最优的答案即可。

wqs 二分的优越处在于,对于原问题,我们需要考虑选了多少个物品,而二分斜率并给每个物品一个多余的代价之后,问题变得不需要再考虑选了多少个物品。

几、细节

大部分题目答案 \(ans_i\) 都是一个整数,所以凸包上的边的斜率,也就是相邻点的答案的差值 \(ans_i-ans_{i-1}\) 也会是一个整数,这种情况只需要二分整数,否则还需要二分实数。

多点共线情况处理起来更麻烦一些,假如说凸包是个这个形态,我们要求出的是 \(B\) 点的纵坐标:

斜率二分到 \(k_2\) 的时候,无论尽量少选的还是尽量多选都不会找到这个 \(B\) 点,但是可以通过截距 \(+km\) 来求出 \(B\) 的纵坐标(注意这里并不是截距 $+k\times $ “check 中选出的物品个数”)。

那么假如钦定每次少选:

当切点在 \(B\) 右侧时,此时切点可能是 \(C\) 及以后的点,斜率一定是错的,不标记答案,令 \(r\gets mid-1\)

当切点在 \(B\) 左侧时,此时切点可能是 \(A\) 及以前的点,斜率可能是正确的,标记答案,令 \(l\gets mid\)

为了能二分到正确的斜率,不会死循环,每次令 $mid\gets \left \lceil \frac{l+r}{2} \right \rceil $,判断继续二分的条件是 \(l<r\)

假如钦定每次尽可能多地选也同理:

当切点在 \(B\) 右侧时,此时切点可能是 \(C\) 及以后的点,斜率可能是正确的,标记答案,令 \(r\gets mid\)

当切点在 \(B\) 左侧时,此时切点可能是 \(A\) 及以前的点,斜率一定是错的,不标记答案,令 \(l\gets mid+1\)

为了能二分到正确的斜率,不会死循环,每次令 $mid\gets \left \lfloor \frac{l+r}{2} \right \rfloor $,判断继续二分的条件是 \(l<r\)

P2619

板子

CF739E

做法一:对 A 类球 wqs 二分,B 类球暴力 dp 记录其选了多少个。\(\mathcal{O}(n^2\log n)\)

(假)做法二:wqs 二分 套 wqs 二分,\(\mathcal{O}(n\log^2n)\).震惊了,这个是假做法吗

做法三:对 A 类球二分,然后内部贪心邻项交换法,这么神奇的吗

posted @ 2022-07-26 11:27  do_while_true  阅读(99)  评论(0编辑  收藏  举报