给定一个正整数数列,和正整数 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
-
思路 1:
二分查找,排好序后,从最小的元素开始遍历,每次通过二分查找在[i+1, right)内找到num[i]*p的位置,计算这种情况下的“距离”,并不断更新全局max变量(记录最长距离) -
code 1:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stdio.h>
#define ll long long
using namespace std;
int n, p;
int seq[100010];
int BinSearch(int i, ll x){
if(seq[n-1] <= x) return n; //所有数都比x小,返回n
int left = i+1, right = n, mid;
while(left < right){
mid = (left + right) / 2;
if(seq[mid] > x) right = mid;
else left = mid+1;
}
return left; //必须返回left,不能是left-1?
}
int main(){
scanf("%d %d", &n, &p);
for(int i = 0; i < n; ++i)
scanf("%d", &seq[i]);
sort(seq, seq+n);
int Max = -1;
for(int i = 0; i < n; ++i){
ll max = (ll)seq[i] * p;
int now = BinSearch(i, max) - i;
if(now > Max) Max = now;
}
printf("%d", Max);
return 0;
}
- code 1-2:用upper_bound代替二分查找
#include <algorithm>
#include <cstdio>
#define ll long long
using namespace std;
int n, p;
ll seq[100010]; //这个seq必须用ll,因为后面upper_bound查找的是>max(ll)的第一个元素
int main(){
scanf("%d %d", &n, &p);
for(int i = 0; i < n; ++i){
scanf("%lld", &seq[i]);
}
sort(seq, seq+n);
int Max = -1;
for(int i = 0; i < n; ++i){
ll max = seq[i] * p;
//upper_bound返回[seq+(i+1), seq+n)区间内超过max的第一个元素的指针
int pos = upper_bound(seq+i+1, seq+n, max) - seq - i;
if(pos > Max) Max = pos;
}
printf("%d", Max);
return 0;
}
-
思路 2:
Two-Point法:思路同1044Shopping in Mars -
code 2:
#include <algorithm>
#include <cstdio>
#define ll long long
using namespace std;
int n, p;
ll seq[100010]; //这个seq必须用ll,因为后面upper_bound查找的是>max(ll)的第一个元素
int main(){
scanf("%d %d", &n, &p);
for(int i = 0; i < n; ++i){
scanf("%lld", &seq[i]);
}
sort(seq, seq+n);
int left = 0, right = 0, len = 1;
while(left < n && right < n){
while(right < n && seq[right] <= seq[left] * p){
len = max(len, right-left+1);
right++;
}
left++;
}
printf("%d\n", len);
return 0;
}
- T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010, INF = 1000000010;
int num[maxn];
int UpperBound(int l, int r, int x){
while(l < r){
int mid = (l + r) / 2;
if(num[mid] > x){
r = mid;
}else{
l = mid + 1;
}
}
return l;
}
int main(){
int n, p;
scanf("%d %d", &n, &p);
for(int i = 0; i < n; ++i){
scanf("%d", &num[i]);
}
sort(num, num+n);
int Max = 0, max_element = -1;
for(int i = 0; i < n; ++i){
int limit = num[i] * p;
if(limit < 0) limit = INF;
int r = UpperBound(i+1, n, limit);
Max = max(Max, r - i);
}
printf("%d", Max); //Wrong1: 求的是Perfect Array元素的数量,不是其中的最大元素
return 0;
}