二分答案
什么是二分答案?
将答案区间进行二分,不断缩小答案区间,直到区间缩小到符合题意的答案。
我们又该怎么书写呢?
常用的二分模版:
// 不断缩小答案区间
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;
}
标签:二分,int,mid,long,算法,答案,check
From: https://www.cnblogs.com/yhgm/p/18050603