二分

Stop learning useless algorithms, go and solve some problems, learn how to use binary search.

—— Um_nik

所以,let’s learn how to use binary search。。。

让我们先看一道题:

如果让你在1~100中猜一个数,每次你猜完我会告诉你大了或小了,你会先猜多少?50

这时你相当于得到了一个新的范围1~49

这时你相当于得到了一个新的范围51~100

输出答案

其实,你刚刚已经完成了一部分二分,然后就是代码实现部分

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//查找x的位置
int find(int x)
{
int l = 1 ,r = n + 1;
while(l < r)
{
int mid = (l + r)/ 2; //防止溢出
if(a[mid] >= x)
r = mid; //小于中间的数,在左区间
else
l = mid + 1; //大于中间的数,在右区间
}
if(a[l] == x)
return l;
if(a[l] != x)
return -1;
}

二分的复杂度是O(logn),一般出现在N2e5N\leq 2e5的题中。二分有时会需要一个check函数(一般O(n))来检查当前状态是否合法

什么时候可以二分?

当有单调性时。

什么是单调性???

即当二分对象的前部分统一满足(或不满足)某一条件,同时后部分相反时我们称它有单调性

二分查找

即上面的那个例子,我们可以用二分查找一个数在数组中的位置

时间复杂度为排序复杂度O(nlogn)+二分复杂度O(logn)

二分答案

Codeforces 911B

可以二分最多放几块,每盘中最多min(a,b)min(a,b)块,最少11

二分答案check即可:

Code:

建议读者自己先Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// Problem: B. Two Cakes
// Contest: Educational Codeforces Round 35 (Rated for Div. 2)
// URL: https://codeforces.com/contest/911/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

/*
Name:
Author: xiaruize
Date:
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define rep(i, x, y) for (int i = x; i <= y; i++)
#define repp(i, x, y) for (int i = x; i >= y; i--)
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define double long double
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int N = 1e5 + 10;

// bool st;
int n, a, b;
// bool en;

signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// cerr<<(&en-&st)/1024.0/1024.0<<endl;
cin >> n >> a >> b;
int l = 1, r = min(a, b);
while (l < r)
{
int mid = l + r + 1 >> 1;
if (a / mid + b / mid >= n)
l = mid;
else
r = mid - 1;
}
cout << l << endl;
return 0;
}