Part 1:二分查找
-
二分法找零点
-
lower_bound
-
LIS
-
数据结构上的二分
注意:二分查找可行的前提条件是序列有序!
例题1:[FAIOJ2333]乐谱
直接在前缀和数组上lower_bound
即可。复杂度 O ( n log n ) O(n\log n) O(nlogn)。
二分法求LIS
最长不下降子序列问题可以使用树状数组解决。但有时序列范围很大或序列不是整数序列,此时树状数组的做法需要加一步离散化。但二分法可以直接解决。
设 f i f_i fi为长度为 i i i的不下降子序列末尾的最小值。显然 f i f_i fi单调递增。
在加入新数时,使用upper_bound
查找出 i i i使得 f i − 1 ≤ x < f i f_{i-1}\leq x < f_i fi−1≤x<fi,然后更新 f i f_{i} fi即可。
注意, f f f的初值要设为 + ∞ +∞ +∞。
例题2:[luogu1439]最长公共子序列
一般的最长公共子序列问题是没有复杂度低于 O ( n 2 ) O(n^2) O(n2)的解法的。但本题的两个序列都是排列,所以可转化问题。
设 p i p_i pi为序列 b b b中 a i a_i ai的位置。则问题转化为求 p p p的最长上升子序列。
Part 2:二分答案
二分答案——“反向求解”
使用条件:
题目中的某个条件关于答案的函数是单调的(不需要严格单调)
如果我们已经知道答案,那么可以较容易地反向求出该题目条件。
显然,二分答案往往是对题目的第一步处理,而题目的难点往往在check
的部分。
例题3:[NOIP2015][luogu2678][FAIOJ10153]跳石头
最多移走的石头数关于石头间的距离是单调递增的,满足二分条件。
因此直接二分答案 x x x,然后贪心取走所有与上一个石头距离大于 x x x的石头即可。
复杂度 O ( n log L ) O(n\log L) O(nlogL)
例题4:[luogu1182][FAIOJ30014]序列分段II
最小化最大值。二分答案,问题转化为将序列划分成若干段和不超过 M M M的子段。
如何检验一个已知的最大值 M M M是否可行?
贪心。只要再加一个数就超过 M M M了,就新开一段。容易证明这样做一定是最优的。
复杂度 O ( n log A ) O(n\log A) O(nlogA)
例题5:[NOIP2011][luogu1314][FAIOJ10114]聪明的质检员
本题要求 ∣ S − s ∣ |S-s| ∣S−s∣最小。由题意可知, S S S关于 W W W单调递减。
因此,当 S < s S<s S<s时,要将 W W W减小;当 S > s S>s S>s时,要将 W W W增大。
如何在已知 W W W时计算 S S S?
直接暴力枚举所有区间并计算肯定是不行的。 O ( n 2 ) O(n^2) O(n2)。
将 < W < W <W的值视为 0 0 0, ≥ W \geq W ≥W的值不变,做前缀和即可。
总复杂度 O ( n log W ) O(n\log W) O(nlogW)。
例题6:[NOIP2012][luogu1083][FAIOJ10124]换教室
显然,如果前 x x x个人的订单无法同时满足,那么前 x + 1 x+1 x+1个人的订单也无法同时满足。
因此本题可以二分答案,判断前 x x x个人的订单能否同时满足。
问题转化为:有一个序列 r r r,共有 x x x个操作,每次给区间 [ l j , r j ] [l_j,r_j] [lj,rj]减 d j d_j dj,问操作结束后序列是否全非负。
这是经典的一维差分模板题。
复杂度为 O ( n log n ) O(n\log n) O(nlogn)。
Part 3:01分数规划
01分数规划是处理比值最优化问题的算法。
例题7:[FAIOJ30012]Best Cow Fences
本题要求最大化平均值。
显然,平均值越大,可行子段就越短。因此满足二分的条件。
二分平均值 W W W,令b_i=a_i-W,则 ∑ i = l r b i ≥ 0 \sum_{i=l}^rb_i\geq 0 ∑i=lrbi≥0即 ∑ i = 1 r a i ≥ ( r − l + 1 ) W \sum_{i=1}^ra_i\geq (r-l+1)W ∑i=1rai≥(r−l+1)W,即 a l a_l al到 a r a_r ar的平均值 ≥ W \geq W ≥W。
因此对 b b b数组求前缀和,维护前缀和的后缀最大值,枚举左端点,检验是否存在非负的长度 ≥ L \geq L ≥L的子段即可。
复杂度为 O ( n log A ) O(n\log A) O(nlogA)。
例题8:[luogu4322][FAIOJ21608]最佳团体
本题要求 ∑ P i ∑ S i \frac{\sum P_i}{\sum S_i} ∑Si∑Pi最大。
如果不看 S S S,那么这道题本质上是一个树形背包问题。模型的建立很显然。
我们还是二分这个比值 W W W。考虑问题的转化。
令 A i = P i − W ∗ S i A_i=P_i-W*S_i Ai=Pi−W∗Si,则 ∑ A i ≥ 0 \sum A_i\geq 0 ∑Ai≥0即 ∑ P i ≥ ∑ W ∗ S i = W ∗ ∑ S i \sum P_i\geq \sum W*S_i=W*\sum S_i ∑Pi≥∑W∗Si=W∗∑Si,即 ∑ P i ∑ S i ≥ W \frac{\sum P_i}{\sum S_i}\geq W ∑Si∑Pi≥W。
因此将 A i A_i Ai视为点权做树形背包即可。
复杂度为 O ( n 2 log P ) O(n^2\log P) O(n2logP)。
Part 4:分治
分治包含序列分治和树分治等。NOIP范围内仅涉及序列分治。
经典应用:
-
归并排序
-
大规模逆序对问题
-
平面上的最近点对问题
例题9:[NOIP2011][luogu1309][FAIOJ1884]瑞士轮
本题最直接的思路就是每一轮比赛算完分之后都对整个数组重新排序,这样复杂度会达到 O ( R n log n ) O(Rn\log n) O(Rnlogn),TLE!
但注意到每轮比赛中都有一半人胜利,另一半人失败,而这两部分人内部的排序是不变的。
这正是归并排序合并两个有序数组的部分。可以 O ( n ) O(n) O(n)解决。
总复杂度为 O ( R n + n log n ) O(Rn+n\log n) O(Rn+nlogn)。
总结
从以上几道例题即可看出,二分的思想非常广泛,而二分答案和分数规划更是可以和几乎所有的算法相结合形成一些看似无法直接处理的题目。在后面的图论和数据结构的例题中,还会经常出现二分的思想。