# 二分法
## 套路
### 寻找满足条件的最小值(整数):
```c++
while (l <= r)
{
int mid = (l + r) / 2;
//不同之处
if (…… < / > 条件)
l = mid + 1;
else
r = mid - 1;
}
//l为要寻找的值
```
这是因为循环会在满足条件时减小右边界,不断向左移,直到找到满足条件的最小值
### 寻找满足条件的最大值(整数):
```c++
while (l <= r)
{
int mid = (l + r) / 2;
//不同之处
if (…… <= / >=条件)
l = mid + 1;
else
r = mid - 1;
}
//r为要寻找的值
```
这是因为循环会在满足条件时增大左边界,不断向右移,直到找到满足条件的最大值
### 寻找某个精确的值(非整数)
```c++
while (r - l > 0.001)
{ // 精度为小数点后两位
double mid = (l + r) / 2;
if (…… < / > 条件) //等于的话也无所谓
r = mid;
else
l = mid;
}
//mid为要寻找的值
```
左右差值小于 0.001 后输出mid值,此时 mid 值的精度必能满足要求:小数点后两位
此时不必再考虑到底是满足条件的最小值还是最大值
### 关键:
1.条件到底是什么
2.如何判断是否满足条件
3.不满足条件时,什么时候向左搜索,什么时候向右搜索
4.是要找满足条件的最小值还是最大值
### 举例:查找递增数组中某个数的第一个/最后一个下标
#### 题意:
输入 *n* 个不超过 109109 的单调不减的(就是后面的数字不小于前面的数字)非负整数 a1,a2,……,an,然后进行 *m* 次询问。对于每次询问,给出一个整数 *q*,要求输出这个数字在序列中第一次/最后一次出现的编号,如果没有找到的话输出 −1 。
#### 输入:
```c++
//找第一个
11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6
```
#### 输出:
```
1 2 -1
```
#### 代码:
```c++
#include <vector>
#include <iostream>
int main()
{
int n, m;
std::cin >> n >> m;
std::vector<int> a(n), b(m);
for (int i = 0; i < n; i++)
std::cin >> a[i];
for (int i = 0; i < m; i++)
std::cin >> b[i];
for (int x : b)
std::cout << find_x(a, 0, n - 1, x) + 1 << ' ';
std::cout << std::endl;<