PAT (Basic Level) Practice 1030 完美数列 (25分) (使用upper_bound进行二分查找!)
1.题目
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
2.题目分析
使用uppper_bound函数进行二分查找
知识补充(https://blog.csdn.net/qq_40160605/article/details/80150252)
在从小到大的排序数组中
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
3.代码
#include<iostream>
#include<algorithm>
using namespace std;
long long list[100001];
int main()
{
long long n, p;
cin >> n >> p;
for (int i = 0; i < n; i++)
cin >> list[i];
sort(list, list + n);
long long maxa = 0;
for (int i = 0; i < n; i++)
{
int index = upper_bound(list+i, list+n, list[i] * p)-list;
if (index == n)index--;
while(list[index]>list[i]*p)index--;//可能所有的数字都不满足,但是upper_bound返回的是n-1
maxa =(maxa> index - i+1)?maxa:(index-i+1);
}
cout << maxa;
}