# Basic algorithm -- binary search and binary answer analysis

### 0x04 two points

There are two dichotomous ways:

```int l = 0, r = n + 1;
while(l < r)
{
mid = l + (r - l) / 2;
if(a[mid] >= x) r = mid;
else l = mid + 1;

}

while(l < r)
{
mid = (l + r + 1) << 1;
if(a[mid] <= x) l = mid;
else r = mid - 1;
}
```

1. Cyclic condition l < R

It can be guaranteed that the final l == r at this time, the mid must fall on the correct answer

2. Change of l and r

The first is to find the lower_bound(x), the smallest number greater than or equal to X. when a [mid] > = x, the numbers after mid are certainly not satisfied, and mid may be the correct answer, so r = mid; When a [mid] < x, mid must not be the correct answer, so l = mid + 1;

The second is to find the maximum number less than or equal to X. when a [mid] < = x, the numbers before mid are certainly not satisfied, and mid may be the correct answer, so l = mid; When a [mid] > x, mid must not be the correct answer, so r = mid - 1;

3. Change of mid + [0, n+1]

Mid = L + (R - L) / 2 prevents overflow

Mid = (R + l + 1) < 1 makes mid not equal to l, so as to avoid that when r - l = 1, mid is always equal to l, and an endless loop is formed after entering the l = mid statement;

The original interval [1, n] is extended to [0, n+1] to deal with the case of no solution

##### Summary: specific analysis

1. Select the corresponding left and right half intervals according to the comparison results between a[mid] and the target value

2. According to the target value to be found, judge whether mid + 1 and mid - 1 are not the correct answer, and then select one of the two supporting half schemes: "r = mid, l = mid + 1, mid = L + (R - L) / 2" and "L = mid, r = mid - 1, mid = (L + R + 1) < < 1"

3. The termination condition is l == r, and this position is the final answer.

#### Dichotomy on real number field

1. Generally, when k decimal places are reserved, take the precision eps = 1e-(k+2)

2. while condition is L + EPS < R

```while(l + eps < r)
{
double mid = (l + r) / 2;
if(calc(mid)) l = mid;
else r = mid;

```

3. If it is difficult to determine the accuracy, the fixed number of cycles is used for bisection, and the accuracy is often even higher

```For(i, 1, 100)
{
double mid = (l + r) / 2;
if(calc(mid)) l = mid;
else r = mid;
}
```

#### Example aw102 maximum matrix sum of pre example -- POJ1050

```int main ()
{
cin >> n;
For(i, 1, n)
For(j, 1, n) cin >> mat[i][j];
For(i, 1, n)
{
clr(s);
For(j, i, n)
{
For(k, 1, n) s[k] += mat[j][k];
int num = 0;
For(k, 1, n)
{
num += s[k];
if(num <= 0) num = 0;
ans = max(ans, num);
}
}
}
cout << ans << endl;
return 0;
}
```

Traverse from row i to row j, and save the sum of each column from row i to row j with sum under different i conditions. After saving row j, find the maximum subarray sum once and compare it with ans, so as to change the two-dimensional into one-dimensional, and find the sum of the maximum submatrixes for all matrices in different rows, and finally get the sum of the maximum matrices

#### Example aw102 best cattle fence

Main idea: find the maximum average of all subsequences with length not less than L (sum of subsequences / length of subsequences)

Train of thought analysis: real number field dichotomy + prefix and

We can calculate the maximum average by subtracting the average from each item of the sequence to find that the sum of subsequences with length ≥ L is non negative. Since the maximum average is required, the larger the sum of non negative subsequences is, the better (because each item of the subsequence can subtract a larger average and still ensure non negative), that is, after subtracting itself from each item of the sequence, Maximum subsequence and nonnegative maximum mean

**Solution steps: 1. First use the real number field to get the average**

```	double l = 0, r = 1e6;
double mid;
double eps = 1e-5; //Keep three decimal places
while(l + eps < r) //Real number field dichotomy
{
mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
}
```

​ 2. A new sequence is generated by using the average, and the prefix sum is calculated

​ 3. The sum of the largest subsequences of the new sequence is obtained by using the idea of prefix sum, and whether it is ≥ 0 is judged

```bool check(double mid)
{
For(i, 1, n) s[i] = s[i-1] + a[i] - mid; //Step 2 find the prefix and of the new sequence
double minn = 1e6;
for(int i = 0, j = f; j <= n; j++, i++) //Using the idea of two pointers, first set the position difference of the pointer to L, and then add 1 synchronously every cycle
{
minn = min(minn, s[i]); //minn must be the minimum prefix sum that all S[j] can subtract, and subtracting the minimum is the sum of the maximum subsequences
if(s[j] - minn >= 0) return true; //If the conditions are met, continue dichotomy to find the optimal solution
}
return false;
}
```

Full Code:

```//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>

#define For(i,a,b) for (int i=(a);i<=(b);++i)
#define Fod(i,b,a) for (int i=(b);i>=(a);--i)
#define mls multiset
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define pob pop_back
#define itt iterator
#define clr(x) memset(x, 0, sizeof(x));

typedef long long ll;
typedef unsigned long long ull;

using namespace std;
const int MAXN = 0x7fffffff;

int n, f;
double a;
double b;
double s;

bool check(double mid)
{
For(i, 1, n) s[i] = s[i-1] + a[i] - mid;
double minn = 1e6;
for(int i = 0, j = f; j <= n; j++, i++)
{
minn = min(minn, s[i]);
if(s[j] - minn >= 0) return true;
}
return false;
}

int main ()
{
cin >> n >> f;
For(i, 1, n) cin >> a[i];
double l = 0, r = 1e6;
double mid;
double eps = 1e-5;
while(l + eps < r)
{
mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
}
cout << (int)(r*1000) << endl;
return 0;
}
```

Posted by milesap on Thu, 04 Nov 2021 13:20:24 -0700