1.牛可乐和魔法封印
下面的这个算是我自己学习这个二分算法的第一道正式的题目:关于这个非常奇怪的题目,但是看看这个测试用例就知道这个题目需要我们做的这个事情了;
输入的5表示我们输入的数据的个数,3表示的就是我们需要查找的数据范围的要求,比如这个2-6之间,在我们输入的5个数据里面,就是2345这四个符合要求的数据;
1-5这个区间,显然输入的这五个数据都是没有问题的,3-3这个区间,显然只有一个数据符合要求,然后把这个符合要求的数据的个数直接输出即可
下面的这个是我们的代码:
1)先看一下主函数里面的输入的内容,循环输入n个数据,q表示的就是我们的查询的次数,其中每一次进行查询的时候都需要进行两个元素的输入即可,在这个输入的过程之哦吼调用我们封装的这个自定义函数,用来计算这个数组里面的符合数据范围的要求的数据的个数即可;
2)在我们的这个自定义函数里面,其实还是一样的道理,就是找到这个大于等于x第一次出现的位置,使用二分的思想;
然后找到这个第一次符合元素的位置,如果结束之后这个指针的指向还是小于x的,证明这个数据里面就没有符合要求的这个元素,我们直接返回0即可;
第二个循环里面查找的就是符合要求的元素里面的最后一个位置,这个时候我们也是进行这个区间的划分,把这个区间划分成为小于等于y和大于y的两个部分,当这个过程结束的时候,我们直接判断一下这个时候left指向的位置是不是符合要求的,如果是大于y的,证明我们的这个数组里面的元素都是大于y的,也就是说我们的这个数组里面是没有符合要求的这个元素的,这个时候我们直接返回这个0即可;
3)最后需要我们返回这个符合要求的区间元素的个数,我们直接使用定义的两个下标相减,看看这个+1,-1细节的处理一下即可;
#include<iostream>using namespace std;const int N=1e5+10;int n;int a[N];int binary_search(int x,int y){ int left=1,right=n; while(left<right) { int mid=(left+right)/2; if(a[mid]>=x) right=mid; else left=mid+1; } if(a[left]<x) { return 0; } int temp=left; left=1,right=n; while(left<right) { int mid=(left+right+1)/2; if(a[mid]<=y) left=mid; else right=mid-1; } if(a[left]>y) return 0; return left-temp+1;}int main(){ cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } int q;cin>>q; while(q--) { int x,y;cin>>x>>y; cout<<binary_search(x,y)<<endl; } return 0;}
2.A-B数对
下面的这个题目我们之前是有写过的,是在哈希表的文章里面,当时是使用的这个哈希表进行统计的;这次我们使用这个二分的思想进行求解;下面的这个就是我们的对应代码:
1)首先根据这个题目里面的数据范围确定这个数据的类型应该是这个Longlong类型的;
2)不断的进行这个数据的输入,因为这个输出的是c,我们想要求解的事这个a-b符合要求的数组的组数,因此我们只需要使用这个a-c,看看这个里面有多少个符合要求的a-c即可,这样,我们就可以把这个题目转换为我们在这个数组里面去找到这个a-c出现的次数即可;
3)上面我们已经知道了这个题目如何去使用这个二分的四星阿哥,记下来就是实现的问题,因为我们的这个a放到这个数组里面去啦,我们需要使用二分去查找是a-c,在下面的这个代码里面,我们使用b来进行的这个定义,因此只需要去这个数组里面找到这个b即可;
4)ret就是进行的这个相关的符合条件的这个数据的个数的统计,我们使用的不是传统的这二分的思路,而且调用的STL里面的两个函数,也就是upper_bound函数和我们的lower_bound函数;
我们直接进行两个函数的返回值的相减,得到的就是这个符合要求的数据的个数,里面的函数参数诸如这个a+i实际上利用的就是指针的指向的问题,为什么这个最开始是从a+1开始的,因为这个我们进行数据输入的时候就是从1开始的,因此我们寻找这个符合要求的数据个数的时候也是从下标为1的元素开始的;这个是需要我们注意的这个地方;
#include<iostream>#include<algorithm>typedef long long LL;const int N = 2e5 + 10;LL n, c;int a[N];using namespace std;int main(){ cin >> n >> c; for (int i = 1; i <= n; i++) { cin >> a[i]; } sort(a + 1, a + 1 + n); LL ret = 0; for (int i = 2; i <= n; i++) { LL b = a[i] - c; ret += upper_bound(a + 1, a + i, b) - lower_bound(a + 1, a + i, b); } cout << ret << endl; return 0;}