PAT A1085 Perfect Sequence
Sample Input:
10 8
2 3 20 4 5 1 6 7 8 9
Sample Output:
8
word | meaning |
---|---|
parameter | 〈数〉参量 |
as many numbers as possible to | 尽可能多的 |
-
思路 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; //Wrong 1:溢出判断,样例5
int r = UpperBound(i+1, n, limit);
Max = max(Max, r - i);
}
printf("%d", Max); //Wrong1: 求的是Perfect Array元素的数量,不是其中的最大元素
return 0;
}
- T4 code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> num;
int UpperBound(int left, int right, ll aim)
{
while(left < right)
{
int mid = (left + right) / 2;
if(num[mid] > aim)
{
right = mid;
}else
{
left = mid + 1;
}
}
return left;
}
int main()
{
int n, Max = 0;
ll p;
scanf("%d %lld", &n, &p);
num.resize(n);
for(int i = 0; i < n; ++i)
{
scanf("%lld", &num[i]);
}
sort(num.begin(), num.end());
for(int i = 0; i < n; ++i)
{
int pos = UpperBound(i+1, n, num[i] * p);
Max = max(Max, pos - i);
if(pos == n) break;
}
printf("%d", Max);
return 0;
}