Given a sequence of positive integers and another positive integer p. The sequence is said to be a perfect sequence if M≤m×p where M and mare the maximum and minimum numbers in the sequence, respectively.
Now given a sequence and a parameter p, you are supposed to find from the sequence as many numbers as possible to form a perfect subsequence.
Input Specification:
Each input file contains one test case. For each case, the first line contains two positive integers N and p, where N (≤105) is the number of integers in the sequence, and p (≤109) is the parameter. In the second line there are Npositive integers, each is no greater than 109.
Output Specification:
For each test case, print in one line the maximum number of integers that can be chosen to form a perfect subsequence.
Sample Input:
10 8
2 3 20 4 5 1 6 7 8 9
Sample Output:
8
--------------------------------------这是题目和解题的分割线--------------------------------------
我好傻题目都看错了,以为是求最大值,原来是最长完美序列的长度(︶︹︺)
求小于(最小值(序列最左端)*参数p)的最大值(序列最右端),可以转换为,先找到大于这个式子的第一个值,则最大值在这个值的前一个位置。这个过程可以用二分法的变形版,再结合for循环,把最小值(序列最左端)当作已知值来扫描最大值。
先来回顾一下最熟悉的二分法。
//好像也没什么值得回顾的二分法
#include<cstdio>
int n,i,a[100],x;
int findN(int x,int a[])
{
int left = 0,right = n-1;
while(left<=right)
{
int mid = (left+right)/2;
if(a[mid]==x) return mid;
else if(a[mid]<x) left = mid+1;
else right = mid-1;
}
return -1;
}
int main()
{
scanf("%d%d",&n,&x);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("%d",findN(x,a));
}
再是本题的代码
#include<cstdio>
#include<algorithm>
using namespace std;
int n,i,a[100005];
long long p; //10^9次方不能用int存储
int f(int i,long long q)
{
//返回n不是n-1,因为这个函数是返回大于式子的值的坐标
if(a[n-1]<=q) return n;
int left = i,right = n-1;
//和二分法不同的是,这里靠left==right作为找到的标志
while(left<right)
{
int mid = (left+right)/2;
//如果中间的数大于该式子,那它可能正是要找的数,则令不要处理mid直接赋值
if(a[mid]>q) right = mid;
else left = mid+1;
}
return left;
}
int main()
{
scanf("%d%d",&n,&p);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
//二分法要递增序列
sort(a,a+n);
//maxN存最大长度,最小值至少为1(自身)
int maxN = 1;
//i作为序列最左端进行遍历,求出n个完美序列长度,取最大值
for(i=0;i<n;i++)
{
int x = f(i,a[i]*p);
//实际上是x-1+i+1
maxN = max(maxN,x-i);
//x-1:x是第一个大于式子的值,而序列的最右端是小于式子的最大值,需要-1
//+1:结尾+1是因为序列长度 = 末端坐标 - 始端坐标 + 1
}
printf("%d",maxN);
return 0;
}