分组
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;
}