整数二分
二分是有顺序要求得
整数二分有两个模板
根据边界分法不同分成两个模板
//
//整数二分 (需要考虑边界问题)
//有两个模板
//模板一 (寻找第一个大于等于x的数 )
//[l,mid],[mid+1,r]
int b[100000]
int erfen(int x , int m)//x是要寻找的数m右边界
{
int l=0,r=m;
while(l < r)
{
mid = l + (r-l) / 2;//或者mid=(l+r)/2
if(b[mid] >= x)
r=mid;
else
l=mid+1;
}
if(b[l]==x)
return 1;
else
return -1;
}
//模板二(寻找最后一个大于等于x的数)
//[l,mid-1],[mid,r];
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = (l + r + 1)/2;//注意加一防止死循环
if (b[mid] <= x)
l = mid;
else
r = mid - 1;
}
if(b[l]==x)
return 1;
else
return -1;
}
浮点数二分主要是要知道精度问题
https://www.acwing.com/problem/content/682/
可以参照acwing上的这道题
浮点数二分就一个模板
//
//浮点数二分什么时候用(最优解 →判定问题 )可转化思想
//浮点数二分不用考虑边界问题边界全部都是mid即可
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int w[N];
bool check(double len)//剪长度为 len 的绳字是否能到 m 根
{
int res = 0;
for (int i = 0; i < n; i++)
{
res += w[i] / len;//一根绳子能剪出多少长度为 m 的绳子
if (res >= m)
return true;
}
return false;
}
int main()
{
cin >> n >> m;
for (int i = 0; i <n; i ++ )
cin >> w[i];
double l = 0, r = 1e9;
while (r - l > 1e-4)//精度问题(看题目上的结果小数点有几位就加二)
{
double mid = (l + r) / 2;
if (check(mid))
l = mid;
else
r = mid;
}
printf("%.2lf\n", r);
return 0;
}
这只是基本的二分的模板但是真要做出二分的题目还是挺难的
二分的转化应用有许多
查找最后一个小于给定值的元素
这只是一个引子有许多问题当暴力做法超时是就应该想到二分做法是否合适
来通过从答案和mid的关系来确定mid+1还是mid-1
或者确定是l=mid还是r=mid;
主要是考虑将某个问题转化为最优解问题来求
//
while (start <= end)
{
int mid = start + (((end - start)) >> 1);
if (nums[mid] == target)
{
// 需要判断前一位是否也等于 target,不等于直接返回
if (nums[mid - 1] != target)
{
return mid;
}
// nums[mid -1] == target
end = mid - 1;
}
else if (nums[mid] < target)
{
start = mid + 1;
}
else
{
end = mid - 1;
}
}
return -1;
}