解题过程的小记录,如有错误欢迎指出。
难度:三星(第一道二分算法题,二分模板要背一下 ,去背二分的STL容器)
题目分析
满足题中给出的条件:MAX<=MIN*p的数列被称为完美数列,给出一组数,要求组成完美数列的最长长度(或者说组成的数字的个数)
注意点
- 题中给出的数字的饭碗刚好卡在int的临界点附近,要注意类型的选择
我的解题过程
思路
本题属于从有序数列中找出一个值满足某一条件的类型题,用二分算法可以解决此类问题
- 把输入的数字进行递增排序
- 分析条件,为了避免int越界,可以把条件替换为t=MAX/p<=MIN,固定MAX即可找出满足条件的最小MIN值(找最小是为了让长度更大,在其中包括的数字最多)
- 如果扫描到的MAX的下标 减去 已经找出的最长长度为负,就没有必要再往下找
bug
做的过程中有翻书找模板,套了模板后一次过了
代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n;
vector<int> num;
int comp(int n1, int n2) {
return n1 < n2;
}
int solve(double t, int left, int right) {
while (left < right) {
int mid = (left + right) / 2;
if (num[mid] >= t) {
right = mid;
}
else {
left = mid + 1;
}
}
return left;
}
int main()
{
double p;
cin >> n >> p;
for (int i = 0; i < n; i++) {
int nn;
scanf("%d", &nn);
num.push_back(nn);
}
sort(num.begin(), num.end(), comp);
int ans = 0;
for (int i = n - 1; i >= 0; i--) {
double t = num[i] / p;
int length = i - solve(t, 0, i) + 1;
if (length > ans) ans = length;
if (i - (length - 1) <= 0) break;
}
cout << ans;
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- 比较哪个长度最长可以采用ans=max(ans,length)的方法
- 二分算法在STL中直接有模板【呜呜呜太好了,不用背了,STL就是坠dior的】【用这个的话要记得返回的不是下标而是一个iterator,如果想要下标需要与begin()相减】
可以适当参考以下两个链接
C++中lower_bound函数和upper_bound函数.
关于lower_bound( )和upper_bound( )的常见用法. - 如果是简单的int排序可以直接sort(num.begin(),num.end()),不需要自己另外写
- 柳神的代码是没有采用二分的,直接双层嵌套循环找,不过保存了长度,每次子嵌套都加上长度后再判断,可能这就是循环嵌套没有超时的原因吧