【基础算法】二分答案

二分答案

什么是二分答案?

将答案区间进行二分,不断缩小答案区间,直到区间缩小到符合题意的答案。

我们又该怎么书写呢?

常用的二分模版:

// 不断缩小答案区间
while (l <= r)
{
    int mid = l + r >> 1;
    if (check(mid)) r = mid - 1;
    else l = mid + 1;
}

模版的含义

\(l\) 表示答案的左端点,一般是 \(0\) 或者 \(1\)

\(r\) 表示答案的右端点,这个就要根据题目来确定了。

check函数怎么写?

根据题目的要求

例一:P9240 冶炼金属

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 10010;
int a[N], b[N];
int n;
bool check1(int x)
{
	for (int i = 1; i <= n; i++)
		if (a[i] / x > b[i]) 
			return true;
	
	return false;
}
bool check2(int x)
{
	for (int i = 1; i <= n; i++)
		if (a[i] / x < b[i])
			return true;
	
	return false;
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i] >> b[i];
	int l1 = 1, r1 = 1e9;
	while (l1 <= r1)
	{
		int mid = (LL)(l1 + r1) / 2;
		if (check1(mid)) l1 = mid + 1;
		else r1 = mid - 1;
	}
	int l2 = 1, r2 = 1e9;
	while (l2 <= r2)
	{
		int mid = (LL)(l2 + r2) / 2;
		if (check2(mid)) r2 = mid - 1;
		else l2 = mid + 1;
	}
	cout << l1 << ' ' << r2 << endl;
	return 0;
}

例二:P2440 木材加工

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010;
int n, k;
int a[N];
bool check(int x)
{
	int cnt = 0;
	for (int i = 1; i <= n; i++)
	{
		cnt += a[i] / x;
	}
	return cnt < k;
}
int main()
{
	cin >> n >> k;
	LL sum = 0;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		sum += a[i];
	}
	int l = 1, r = sum / k;
	while (l <= r)
	{
		int mid = l + r >> 1;
		if (check(mid)) r = mid - 1;
		else l = mid + 1;
	}
	cout << r << endl;
	return 0;
}
posted @ 2024-03-03 20:09  高明y  阅读(67)  评论(0)    收藏  举报