整数二分,浮点数二分模板

整数二分

二分是有顺序要求得
整数二分有两个模板

根据边界分法不同分成两个模板
// 
//整数二分 (需要考虑边界问题)
//有两个模板 
//模板一 (寻找第一个大于等于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;
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值