Divide and conquer (1) - Dichotomy: binary search + binary answer

Bisection is a common trick that reduces the original O(n) complexity to O(log n) . However, dichotomy also has limitations and can only be used in a monotonically ordered set. Therefore, for a topic, we must first judge whether it is divisible, and then divide it.

1. Binary search

1.1 Ideas

In an ordered set that is not strictly monotonic, if we want to find the position of an element, we can use l to store the lower bound and r to store the upper bound, and then divide the whole set into two halves, by comparing the middle element of the set with the target element , to determine whether the target element is in the left or right half of the set (if the middle element is the same as the target element, exit the function and return the position of the middle element), and then update the upper and lower bounds. Continue to do this until l>r.

1.2 Template

// Here is an example of finding elements in a non-strictly monotonically increasing array
int find(int l,int r,int v)//l stores the upper bound, r stores the lower bound, and v is the target element
{
    if(l>r) return -1;//If not found, return -1
    int mid=(l+r)>>1;//mid is the position of the middle element. Here, the bit operation is used to improve the efficiency, which is equivalent to "int mid=(l+r)/2;" (for bit operation, please refer to https ://blog.csdn.net/chenxiaoran666/article/details/79770278)
    // Compare the middle element with the target element
    if(sum[mid]==v) return mid;//The middle element is the same as the target element, then exit the function and return the position of the middle element
    else if(sum[mid]>v) find(l,mid-1);//The middle element is greater than the target element, update the upper bound to the position of the middle element -1
    else find(mid+1,r);//The middle element is smaller than the target element, and the lower bound is updated to the position of the middle element +1
}

Two-point answer

2.1 Ideas

When encountering the problem of extremum value, if the answer to the problem is divisible, we can also use the dichotomy method to solve it. Still use l to store the lower bound, r to store the upper bound, and then use the verification function check() to judge whether the intermediate value of l and r is feasible as the answer, and constantly update the upper and lower bounds, which is extremely efficient.

2.2 Template

// Here is an example of finding the maximum value
void find(int l,int r)
{
    if(l>r) return;//When the upper bound is greater than the lower bound, exit the function
    int mid=(l+r)>>1;//mid is the middle value of l and r
    //Use the verification function check() to judge whether the intermediate value of l and r is feasible as the answer, and the check() function should be written by yourself according to the situation of the question
    if(check(mid)) ans=mid,find(mid+1,r);//If feasible, update the answer and update the lower bound to the position of the middle element + 1
    else find(l,mid-1);//If it is not feasible, update the upper bound to the position of the middle element -1

}

2.3 Example: 【POJ3122】Pie



Note: If you learned the dichotomy through this literature, please like it before leaving. Of course, you are also welcome to point out the shortcomings of this article in the discussion area. The author will correct this article in time
. Copyright statement: Please indicate the address for reprinting

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325773149&siteId=291194637