解題思路:
二分,O(nlogn)的複雜度纔可以跑10^5的數據。直接找到第一個不滿足條件的下標j,然後j-1即使最後一個滿足條件的下標(即所求下標)。二分函數要麼直接調用函數Upper_bound,要麼自己寫。
注意
1.數據109,由於要查找p*m,可能達到1018,故使用long long 來保存數據
2.要注意最大數據也滿足M<=mp的情況
1)upper_bound若沒找到大於所給數據的數據,則返回end
2)若自己寫函數,則應注意[left, right]要包含所有可能取值,即[0,n](最大的數據也<=mp),而非[0,n-1]
方法1.upper_bound(精簡代碼)
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
#include <map>
#define LL long long
using namespace std;
const int maxn = 100000+5;
vector<long long> num;
bool cmp(long long a, long long b){
return a < b;
}
int main(){
int n;
long long p;
scanf("%d%lld", &n, &p);
for(int i = 0; i < n; i++){
long long x;
scanf("%lld", &x);
num.push_back(x);
}
int maxLen = 0;
sort(num.begin(), num.end(), cmp);
for(int i = 0; i < n; i++){
//找到序列裏第一個>m*p的下標
int j = upper_bound(num.begin()+i, num.end(), num[i]*p) - num.begin();
if(j <= n) maxLen = max(maxLen, j-i+1-1);
//可能找不到滿足條件的值。
//注意這裏找的是第一個不滿足條件的下標,而求的應該是-1後的值
}
printf("%d\n", maxLen);
return 0;
}
方法2:自己實現輸出第一個不滿足條件的數組下標
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
#include <map>
#define LL long long
using namespace std;
const int maxn = 100000+5;
vector<long long> num;
int n;
//數據用long long,題目m*p,而p<=10^9,用int最後一個樣例會數據溢出
bool cmp(long long a, long long b){
return a < b;
}
//如果沒有更大的數
int binarySearch(int i, long long x){
int l = i, r = n;//可能所有元素都比它小..
while(l < r){
//對[left,right]來說,Left==right意味着找到唯一位置
int mid = (l + r)/2;
if(num[mid] > x){
r = mid;
}else if(num[mid] <= x){
l = mid+1;
}
}
return l;
}
int main(){
long long p;
scanf("%d%lld", &n, &p);
for(int i = 0; i < n; i++){
long long x;
scanf("%lld", &x);
num.push_back(x);
}
int maxLen = 0;
sort(num.begin(), num.end(), cmp);
for(int i = 0; i < n; i++){
int j = binarySearch(i, num[i]*p);
maxLen = max(maxLen, j-i);
}
printf("%d\n", maxLen);
return 0;
}