[AHOI2018初中组][二分查找] 分组

以前没正经写过二分查找,就拿这个当作是板子吧

题面

最开始是想二分答案的,但是没有考虑到数据中重复的数值的情况,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;
}

完结~~各位大佬可以大力吐槽QWQ

posted @ 2020-05-31 21:11  ChPu437  阅读(243)  评论(0编辑  收藏  举报