CSP 2022 备战——二分答案

二分,一个重要的算法

在抽象意义上,就是将递增1的数列分成两份

看它是否满足,再继续分割这个数列

看起来很抽象是吧

比方说,这里有一个数列:1 2 3 4 5 6 7 8 9 

我们要找其中一个数的平方=16

对与我们来说,可以一眼看出要找的数是4,第二眼就能确定5的位置

可是计算机不行,所以二分查找闪亮登场

令头head=1,尾tail=9

9的平方是81对吧,所以我们就修改tail,取head+tail的一半也就是5

可是5还是大,那就再取head+tail的一半也就是3

这回3的平方相较16较小,所以我们这次修改head到3

再一次取head和tail的中间值,也就是4

靠着这种方式,我们可以很快确定答案

它的应用性就在于,在一些答案不确定的情况下,可以通过这种查找的方式来确定答案

时间复杂度约为O(log2n)

代码实现:


int x(int n,int k)
{
   int left=0;
   int right=k-1;
  while(left<=right)
  {
    int mid=(left+right)/2;
    if (a[mid]==n)
    {
      return mid;
    }
    if (a[mid]>=n)
    {
      right=mid-1;
    }
    else
    {
      left=mid+1;
    }
  }
  return -1;
}

这就是一个在0到right之间查找的算法

了解了二分查找,那么二分答案也呼之欲出了

现在给定一个升序数组a[n],想查找k在第几个

令“条件”为a[x]大于或等于k,要找最小的x使条件成立

那就可以运用二分查找的思想,先检验数组中间值mid

就可以分为left-mid到mid+1到right上

使用条件:

1.命题可以被归纳成找到使得P(x)(不)成立的最大(小)的x值

2.吧它看作一个bool函数,则它在某一分界线一侧全为真,另一侧全为假

换句话说,二分答案可以用来处理“最大的最小”或“最小的最大”的问题

这就是使用二分答案的基本条件

典中典:

P2678,看一下它是如何判断的

bool check(int dis)
{
    int count=0,last=0;//count代表移走石头的数量,last模拟当前位置
    for(int i=1;i<=n;i++)
        if(a[i]-last<dis)count++;//如果条件符合就移走这块石头
            else last=a[i];//反之就跳过去
    if(count>m)return 0;return 1;//设置终止条件,即移走的石头至多为m
}

 

posted @ 2022-07-22 10:31  美索maysoul  阅读(81)  评论(0)    收藏  举报