原题链接
解题思路
给定一个数p,如果一个序列满足,M≤m×p,则是完美数列,m和M分别是序列中的最大值和最小值。
- 显然,首先对序列进行排序,完美序列一定是该序列的一个连续子序列。
- 排好序后,从小到大枚举每个元素(不一定从首元素开始的是最长的),假定完美序列从该元素开始,此时m、p都已知,如何确定M的位置呢,令 x = m×p,即在序列中寻找第一个大于x的元素,M即为该元素前一个元素,(因为可能有多个重复元素,所以不能找第一个大于等于x的元素)。
upperbound函数:
int upperbound(int l, int r, long long x){//在num数组 [l, r] 中寻找,返回第一个大于x的元素位置
long long mid;
while(l<r){//l==r夹出了答案位置
mid = l+(r-l)/2;
if(num[mid] > x){
r = mid;
}
else{
l = mid+1;
}
}
return l;
}
源代码
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 100010;
long long num[maxn];
int upperbound(int l, int r, long long x){//返回第一个大于x的元素位置
long long mid;
while(l<r){//l==r夹出了答案位置
mid = l+(r-l)/2;
if(num[mid] > x){
r = mid;
}
else{
l = mid+1;
}
}
return l;
}
int main(){
int n;
long long p;
scanf("%d%lld",&n,&p);
for(int i=0; i<n; i++){
scanf("%lld",&num[i]);
}
sort(num, num+n);
// for(int i=0; i<n; i++){
// printf("%lld ",num[i]);
// }
// printf("\n");
int res = -1, j;
for(int i=0; i<n; i++){
j = upperbound(i,n,num[i]*p);
res = max(res, j-i);//j-i为完美序列的元素个数
}
printf("%d",res);
return 0;
}