二分查找与二分答案做题笔记

    1.洛谷p2440

    2.洛谷p1824


洛谷p2440

分析

这道题其实我感觉是一道思维题+二分查找的模版(等于没说),主要在于怎么理解这个找出木头的最小的一段的这句话,其实按照洛谷题解上的说法,这个题因为要找到这个小段木头的最小值所以用二分。

其实在做了一定量的题之后我发现,其实如果一道题在你读懂题目意思的前提之后,你可以先想想这道题用暴力怎么做,用暴力有了思路之后,再用学过的算法进行替换

这个题如果用暴力的话,就是确定一下需要枚举的上界和下界,通过循环一个个进行枚举来实现

但其实这种用枚举来实现的都可以用二分查找来进行替换

这个题我一开始想把所有的木头求和除以k,这样得出一个值,但是这样用样例得出来的是116虽然大于114但是,这样每个木头减去所能减的116的最大倍数后剩下的木头的和是大于116的显然不对所以这时就要思考一下了

如果一根木头整除某个长度,截出来的数量大于或者等于k那么说明这个木头截出来的每个小段还可以更大所以这时候只要写一个函数判断一下是否都大于等于K再用二分的板子判断一下就行

其实把二分的板子背过,这个题想明白木头怎么截的很快就能出结果

#include<iostream>
using namespace std;
long long num[1000005], n, k;
bool pd(long long x)
{
	long long ans = 0;
	for (int i = 1; i <= n; i++)
	{
		ans += num[i] / x;
	}
	return ans >= k;
}
int main()
{
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
	{
		cin >> num[i];
	}
	long long l = 1;
	long long r = 1e9 + 1;
	long long mid = 0;
	while (l + 1 < r)
	{
		mid = (l + r) / 2;
		if (pd(mid))l = mid;
		else r= mid;
	}
	cout << l <<endl;
}

二分的板子背一下(找了好几个算法板子这个比较合适,其实我觉得背一些模板并且理解其中的算法思想对我还是很有帮助的)

	while (l + 1 < r)
	{
		mid = (l + r) / 2;
		if (pd(mid))l = mid;
		else r = mid;
	}
	cout << l << endl;

洛谷p1824

这道题和上面的木材加工这道题可以说是基本一样,也是总结了这种二分题的做法,二分答案类的题基本都可以在枚举的基础上进行加工,创建一个函数来判断这个命题在哪个数的或哪些数的条件下为真,从而再利用二分查找找到这个数,但这些题的难点在于,如何确定这个判断命题是否为真的这个函数的逻辑原理

1.根据现实生活和一些数学关系确定bool函数(一般都可以在题目给的数量中找到一个关系)

2.套用二分的模版即可

这道1824的难点在于如何确定bool函数,这个题里面说了牛棚的数量,所以我们确定第一个牛棚里一定有牛,然后依次枚举后面的牛棚,如果两个牛棚之间的距离大于传入的函数值,则用一个变量dex来记录牛棚的个数当dex>=c时就是判断传入的函数值为真,这个距离就是可取的。

ps:

在这里面-1e9表示负无穷大这样可以让在后面遍历数组的时候,都可以将数组中的数都存在ans里

此外还要注意,将dex的值赋为0因为在二分中会循环进行操作

#include<iostream>
#include<algorithm>
using namespace std;
long long c, n,arr[1000010];
long long sum;
long long l, r;
long long ans;
long long dex;//牛的数量
bool distance(long long x)//关系应该都可以从题里面给的数据中推出来
{
	dex = 0; ans = -1e9;
	for (int i = 1; i <= n; i++)
	{
		if (arr[i]-ans >= x)
		{
			ans = arr[i];
			dex++;
		}
	}
	return dex >= c;
}
int main()
{
	int q = 0;
	cin >> n >> c;
	for (int i = 1; i <= n; i++)
	{
		cin >> arr[i];
	}
	sort(arr+1, arr + n+1);
	l = 0;
	r = 1e9;
	while (l+1< r)
	{
		long long mid = (l + r) / 2;
		if (distance(mid))
		{
			l = mid;
		}
		else
		{
			r = mid;
		}
	}
	cout << l<< endl;
}

总结

所以在算法比赛中,这种二分查找的题大部分代码都是套用二分查找和二分答案的模版并没有太大的难度,只是一开始进行判断的bool函数需要格外注意,需要运用一些思维来构造。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值