分组

P4447 [AHOI2018初中组] 分组

我们考虑二分,但是如果是二分答案,我们发现不好做,于是我们先排序,然后使用二分查找。

我们发现每组只有最后一个数有用,所以我们对于一个组,只需要维护最后一个数和集合大小即可。每次二分,我们每次找 \(\le\) 当前数的最后一组,若满足要求,插入,更新;否则,新开一组。

为什么是最后一组?因为最后一组最新,集合大小最小,更新它更优。

\(\{2,3,3,4,5,7,8,9\}\),前面成立了两组,\(\{2,3\},\{3\}\),我们需要插入的位置是后者。关于如何找最后一组,用 STL upper_bound 找到大于的第一组,往前一个就是小于等于的最后一组。

#include<cstdio>
#include<algorithm>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while

const int N=100010,INF=2e9;
int n,a[N],q[N]{INF},sz[N],cnt,ans=INF;
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    scanf("%d",&n);
    E(i, n)scanf("%d",a+i);
    sort(a+1,a+1+n);
    E(i, n){
        int x=a[i],k=upper_bound(q+1,q+1+cnt,x-1)-q-1;
        if(q[k]==x-1)++sz[k],q[k]=x;
        else q[++cnt]=x,sz[cnt]=1;
    }
    E(i, cnt)ans=min(ans,sz[i]);
    printf("%d",ans);
    return 0;
}
posted @ 2023-09-25 09:52  wscqwq  阅读(18)  评论(0编辑  收藏  举报