以前没正经写过二分查找,就拿这个当作是板子吧
题面
最开始是想二分答案的,但是没有考虑到数据中重复的数值的情况,50 分 WA 了。。。
但是这题显然适合二分查找:
当我们的数据 在数组中是线性排列的,就可以使用二分查找。
需要两个辅助数组:
sz[]
用于记录每个分组的大小g[]
用于记录当前分组后面需要的那个数值
你甚至还会发现这题有点蜘蛛纸牌那味(雾)
不多说闲话,下面是代码:
/*
二分查找:设计一个数组 g[] 表示第 i 个分组中 需要加入的数值
sz[] 表示组大小
先排个序,然后就可满足单调递增即可二分查找
有重复数值时尽量加在最后一个位置
*/
# include <iostream>
# include <cstdio>
# include <algorithm>
# define MAXN 100000+5
using namespace std;
int a[MAXN], n, ans = 100005, sz[MAXN], g[MAXN], cntG;
int main(){
int l, r, mid;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
sort(a+1, a+n+1);
g[0] = 1e9+1; // 可能会被搜到防止爆炸
for(int i = 1; i <= n; i++){
l = 0; r = cntG;
while(l < r){
mid = (l+r+1) >> 1;
if(a[i] >= g[mid]) l = mid;
else r = mid-1;
}
if(g[l] != a[i]){
g[++cntG] = a[i]+1;
sz[cntG] = 1;
} // 注意这里一定是用 l ,不然如果没有进行上一步操作更新 mid 值的话会导致恐怖的 bug
else{
g[l] = a[i]+1;
sz[l]++;
}
} // 对于每个 a[i] 寻找它的位置
for(int i = 1; i <= cntG; i++)
ans = min(ans, sz[i]);
printf("%d", ans);
return 0;
}