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;
}