Day 1 - 二分
整数二分
我们可以做到每次排除一半的答案,时间复杂度 \(O(\log n)\)。
long long l = L, r = R;
while(l <= r) {
long long mid = (l + r) >> 1;
if(mid > x) r = mid - 1;
else l = mid + 1;
}
long long ans = l;
实数二分
我们规定一个精度 \(eps\),以此达到整数二分的效果,时间复杂度为 \(O(\log \frac{R-L}{eps})\)。
为了防止精度过度导致死循环,我们可以限制二分次数,如限制为 \(100\) 次。
实际应用
-
实现求解连续函数的零点(近似解)。
-
\(0/1\) 分数规划。
-
最小比值生成树。
三分法
三分法衍生自二分法,三分法求单峰函数的峰值。
算法流程
设当前搜索域为 \([l,r]\),取该区间的三等分点 \(\text{lmid,rmid}\)。
若满足 \(f(\text{lmid})<f(\text{rmid})\),则可以排除 \([l,\text{lmid}]\)。
若满足 \(f(\text{lmid})=f(\text{rmid})\),则可以排除 \([l,\text{lmid}] \cup [\text{rmid},r]\)。
若满足 \(f(\text{lmid})>f(\text{rmid})\),则可以排除 \([\text{rmid},r]\)。
实数三分
double l = L, r = R;
for(int i = 1; i <= 100; i ++) {
double lmid = l + (r - l) / 3, rmid = r - (r - l) / 3;
if(f(lmid) < f(rmid)) l = lmid;
else r = rmid;
}
double ans = f(l);
整数三分
long long l = L, r = R;
while(r - l > 3) {
long long lmid = l + (r - l) / 3, rmid = r - (r - l) / 3;
if(f(lmid) < f(rmid)) l = lmid;
else r = rmid;
}
long long ans = f(l);
for(int i = l + 1; i <= r; i ++) ans = max(ans, f(i));
算法优化
考虑计算时间复杂度,由于每次搜索域缩减到 \(\frac{2}{3}\)。
因此时间复杂度为 \(O(\log_{\frac{3}{2}} \frac{R - L}{eps})\)。
我们完全可以将 \(\text{lmid}\) 和 \(\text{rmid}\) 不断接近,以此达到使 \(\log\) 的底数无限接近 \(2\)。
应用场景
在单峰性/单谷性能够证明的题目中,三分法都能高效地适配。
本文来自博客园,作者:So_noSlack,转载请注明原文链接:https://www.cnblogs.com/So-noSlack/p/18289729