1.3二分算法
算法理解
二分用于解决答案具有单调性问题(经典最大值最小问题),是一个好的入手点,用一个log的复杂度,将求解答案转化成了判断答案是否合法
实数域上的二分
两种方法:确定精度eps,固定枚举次数,一般后者精度大于前者
T1:
二分最大值,注:如果有一个数本身就大于二分答案,则答案肯定错误,证明:考虑如果只有一个数大于二分答案,其余都正常,可能就会小于分段数,导致答案错误
T2:(T_T)
单纯枚举位置判断这个位置上防具奇偶是不具有单调性的,考虑只有一个位置为奇或全为偶,如何想到的呢:我们先判断是这两种情况的哪一种,显然,如果全部防具加起来为偶,则全为偶,反之则有一鸡,我们可以将这个结论推广,在二分的位置x时,若0~x中有总防具为鸡,则防具个数为鸡的位置必然在前面,反之则在后面,具有单调性
T3:(T_T)
实数内二分平均数,判定是否存在一个长度不小于L的数列,平均数不小于mid,存在性问题,找极端值,就是找平均数最大的序列,平均数是用段的和除以元素个数,我们想只统计段的和,所以,考虑将每一个数都减去平均数,现在问题就转化成了维护一段长度不小于L的和的最大值,考虑统计前缀和,问题又变成了找到对于一个右端点为i的区间,找到一个0~i-L中的最小前缀和,它们相减就是这段的和,找到最大的和,判断它是否大于等于0,是,则存在这样一个序列,具有单调性
T4:
二分选多少宠物,n<50,乱搞即可
T5:
同上题,找到前m大的数,但复杂度太高了,瓶颈在sort排序,考虑将排序优化到O(n),用一种新奇的STL:
std::nth_element(a+1,a+m,a+n+1,cmp);
用法详见OI viki
注:a+m指的是a[m]
T6:
二分答案,dp[i][j]表示用了i根一魔法棒,j根二魔法棒,时可以覆盖的最后一个点的编号,首先预处理一下,从每一个点出发,魔法棒最多覆盖到哪里,然后每次转移即可,注意dp是按照次数来枚举的,而不是位置,所以不存在dp不成立
T7:
二分+贪心
T8:
二分变速器,跑spfa,若有负环则调高,反之则减少,注意有可能是s->t中加了一个负环,此时答案就不正确了,应当先反向建边,然后看终点到起点不需要经过那些边,删去即可